prisma-relay-cursor-connection
prisma-relay-cursor-connection copied to clipboard
CustomEdge generates typescript error
I use prisma-relay-cursor-connection with my NestJS backend, I created a function
async findCategories(): Promise<StoryCategoryConnection> {
return await findManyCursorConnection(
(x) =>
this.prisma.storyCategory.findMany({
...x,
include: {
stories: { take: 1, include: { media: true }, orderBy: { updatedAt: 'desc' } },
},
orderBy: { updatedAt: 'desc' },
}),
() => this.prisma.storyCategory.count(),
null,
{
recordToEdge: ({ stories, ...record }) => ({ node: { ...record, thumbnail: stories[0]?.media } }),
},
);
}
The problem is I get an error in recordToEdge function where I add thumbnail that is a media of the last updated relation story. The error says
Object literal may only specify known properties, and 'thumbnail' does not exist in type '{ stories: ({ media: { id: string; createdAt: Date; updatedAt: Date; name: string; mimeType: string; url: string; frontId: string; backId: string; proofOfAddressId: string; proofOfFundsId: string; storyId: string; }; } & { ...; })[]; } & { ...; }'.ts(2353)
interfaces.d.ts(28, 5): The expected type comes from property 'node' which is declared here on type 'Omit<Edge<{ stories: ({ media: { id: string; createdAt: Date; updatedAt: Date; name: string; mimeType: string; url: string; frontId: string; backId: string; proofOfAddressId: string; proofOfFundsId: string; storyId: string; }; } & { ...; })[]; } & { ...; }>, "cursor">'
Error disappears when I return the list of stories in recordToEdge function, but I don't want to do it, I can also fix that passing
<any, StoryCategory> as an TS argument to findManyCursorConnection but I don't want to use any and Prisma doesn't generate relations as types in e.g. StoryCategory type from prisma schema so I can't pass PrismaStoryCategory as argument instead of any because generic function doesn't see relation and I don't want to create more types than I must
It would be lovely if I could pass type I want as a first argument in findManyCursorConnection or pass it anywhere it would be possible to strictly type my edge type
btw. this problem is weird because I also did it in another function
return await findManyCursorConnection(
(x) =>
this.prisma.game.findMany({
...x,
where,
orderBy: { [field]: direction },
include: { gamesOnCountries: { include: { country: true } }, category: true },
}),
() => this.prisma.game.count({ where }),
{ after, first, before, last },
{
recordToEdge: (record) => ({
node: { ...record, countries: record.gamesOnCountries.map(({ country }) => country) },
}),
},
);
And I don't return gamesOnCountries relation and typescript doesn't scream about it's not present in returned object
Another thing I spotted is that when I use recordToEdge function, type returned from findManyCursorConnection doesn't modify type returned as node, it's still a type returned from prisma query
I'm not sure why TypeScript does not infer the CustomEdge correctly, but here is some pointers:
nullas a third argument is not valid, if you dont want to pass any pagination arguments, you need to use{}- You can pass the generics manually but you will have to also type the
Record(that is returned fromfindMany) yourself: https://github.com/devoxa/prisma-relay-cursor-connection/blob/master/src/index.ts#L12-L17
I'm not sure why TypeScript does not infer the
CustomEdgecorrectly, but here is some pointers:
nullas a third argument is not valid, if you dont want to pass any pagination arguments, you need to use{}- You can pass the generics manually but you will have to also type the
Record(that is returned fromfindMany) yourself: https://github.com/devoxa/prisma-relay-cursor-connection/blob/master/src/index.ts#L12-L17
- Ok,
{}was my first approach but null was for testing if it changes anything in typing, it doesn't - I already found it out, but it would be lovely to type the CustomEdge first, I just tested the "inverse" generic typing and it works, I mean
const fn = <K extends Object<T>, T extends { id: string }>(cb: () => T[], { cb }: { cb: () => K ) => {}
maybe this typing would be more "developer friendly"?