Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide more utility functions (pick, ...) #24

Open
schickling opened this issue Nov 8, 2021 · 3 comments
Open

Provide more utility functions (pick, ...) #24

schickling opened this issue Nov 8, 2021 · 3 comments
Labels
feature New feature or request

Comments

@schickling
Copy link
Collaborator

schickling commented Nov 8, 2021

There's a number of common utility functions which are useful in Contentlayer projects (e.g. a type-safe pick function) like below or here:

image

We should provide these utility functions out of the box with Contentlayer. Candidates:

  • pick: Type-safe function similar to TS Pick type
  • A function that helps with getting the "next" and "previous" document (common in docs pages)
  • A function that helps with sorting documents
  • findById

If you'd like to see an other utility function added, please share your requests/ideas in the comments below. 🙏

@schickling schickling added the feature New feature or request label Nov 8, 2021
@schickling schickling pinned this issue Nov 19, 2021
@alvesvin
Copy link

alvesvin commented Nov 21, 2021

A omit function would be cool also. Sometimes you need to get all but a few fields.

export const omit = <Obj, Keys extends keyof Obj>(obj: Obj, keys: Keys[]): Omit<Obj, Keys> => {
    return keys.reduce((acc, key) => {
        const { [key]: omit, ...rest } = acc;
        return rest;
    }, obj as any)
}

// Maybe this is better because it creates a new object just once
export const omit2 = <Obj, Keys extends keyof Obj>(obj: Obj, keys: Keys[]): Omit<Obj, Keys> => {
    const result = Object.assign({}, obj);
    keys.forEach((key) => {
        delete result[key];
    });
    return result;
}

Maybe deeply picking and omiting by specifing a schema.

dpick(obj, {
    key: true, // Picks all keys from nested object 'key'
    key2: ["key"], // Picks only 'key' field from nested object 'key2'
    key3: {  // Picks all from 'key' nested object but only field 'key' of 'key2' object from object 'key3'
        key: true,
        key2: ["key"]
    }
});

@pmarsceill
Copy link
Contributor

pmarsceill commented Jan 7, 2022

It would be great if pick could be used with non-required fields. For example, if featuredImage was non-required in this case it would return null if it didn't exist on a Document.

pick(doc, [
  'slug',
  'date',
  'title',
  'description',
  'featuredImage',  // non-required field
  ])
)

@schickling
Copy link
Collaborator Author

@pmarsceill that's a great suggestion that's often needed with Next.js getStaticProps. Here's at least a temporary solution (or as TS playground):

type ConvertUndefined<T> = OrNull<{
  [K in keyof T as undefined extends T[K] ? K : never]-?: T[K];
}>;
type OrNull<T> = { [K in keyof T]: Exclude<T[K], undefined> | null };
type PickRequired<T> = {
  [K in keyof T as undefined extends T[K] ? never : K]: T[K];
};
type ConvertPick<T> = ConvertUndefined<T> & PickRequired<T>;

export const pick = <Obj, Keys extends keyof Obj>(
  obj: Obj,
  keys: Keys[]
): ConvertPick<{ [K in Keys]: Obj[K] }> => {
  return keys.reduce((acc, key) => {
    acc[key] = obj[key] ?? null;
    return acc;
  }, {} as any);
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants