-
Notifications
You must be signed in to change notification settings - Fork 201
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
overwrite field
data with computedFields
values
#398
Comments
I ran into this also. In my case, I want to define tags like this my mdx blog posts: tags:
- React
- Next.js
- Something Else ... and transform to an array of objects with the slug work already done, ready for consumption by component(s): tags: [
{ displayName: 'React', slug: 'react' },
{ displayName: 'Next.js', slug: 'nextjs' },
{ displayName: 'Something Else', slug: 'something-else' },
] I ended up working around the typing issues by omitting Note - I acknowledge my solution might be a little cumbersome for others who are importing from // inside contentlayer.config.ts
export const BlogPost = defineDocumentType(() => ({
name: "BlogPost",
filePathPattern: `blog/**/*.mdx`,
fields: {
tags: { type: 'list', required: true, of: { type: 'string' } },
},
computedFields: {
// This takes all the tags defined in the frontmatter (list of strings) and automatically
// derives slugs for them (saving us having to do it each time we consume them).
// This ultimately changes the type of the field from `string[]` (in the frontmatter)
// to `Tag[]` which will be consumed everywhere.
tags: {
type: 'list',
resolve: doc =>
// For some reason, the actual value of `tags` here is PlainArr, so we have to map over the `_array` property instead.
// I don't really care to figure out the typing for that :/
// ref: https://github.com/contentlayerdev/contentlayer/issues/150
/* eslint-disable*/
// @ts-ignore
doc.tags._array.map((tag: string) => ({
displayName: tag,
slug: kebabCase(tag),
})),
/* eslint-enable */
},
})); Inside my custom import type { BlogPost as CLBlogPost } from 'contentlayer/generated';
export type Tag = {
displayName: string;
slug: string;
};
export type BlogPost = Omit<CLBlogPost, 'tags'> & {
// `tags` has a conflicting type due to defining it in both `fields` and `computedFields`
// in the schema, so we've omitted it here and forced it to the type we need.
// ref: https://github.com/contentlayerdev/contentlayer/issues/398
tags: Tag[];
}; Then I can create a base selector to use everywhere: import { allBlogPosts } from 'contentlayer/generated';
import type { BlogPost } from '~/content/blog/types'; // the custom type I've defined above
export const getAllBlogPosts = () => allBlogPosts as unknown as BlogPost[]; Anytime I need to retrieve all the blog posts, I would use the custom Hope it's useful for someone! Though it would be nice if the type wasn't appended so we didn't have to do this. |
Thanks a lot for opening this issue. I agree with the underlying issue but want to be careful with introducing (potentially) breaking changes too quickly. I'll account for this problem in upcoming API iterations. For now as a (unfortunately cumbersome) workaround you can give your computed |
When defining a document with a
field
andcomputedFields
child item with the same name, thecomputedFields
field seems to be appended onto the generated type. Resulting in undesired types for the field.I would have expected the
computedFields
data to overwrite thefield
data, both thedescription
and thetype
.For reference, I am converting a comma separated string of
tags
into a parsed array via thecomputedFields
. Here is an example of my document definition:Generates these types (simplified for the example):
Extra note: It also seems like the
computedFields
children do not supportlist
types, or it may be a bug?The text was updated successfully, but these errors were encountered: