prisma-nestjs-graphql
prisma-nestjs-graphql copied to clipboard
GroupByArgs not compatible with groupBy prisma method
Hello, I think I found an issue, unless it works as expected. I usually directly use the graphql args in the prisma function with no issue. I decided to test the groupBy method but I find some issues when I try to use the GroupByArgs type const as parameter but I got errors about circular references
This is the code I used
@Mutation(() => User)
async createUser(
@Args() params: CreateOneUserArgs,
@Info() info: GraphQLResolveInfo,
) {
const group: UserGroupByArgs = {
by: [UserScalarFieldEnum.name],
};
this.prismaService.user.groupBy(group);
const select = new PrismaSelect(info).value;
params = { ...params, ...select };
return this.prismaService.user.create(params);
}
and these are the errors printing (They also show up in the editor) .
src/users/users.resolver.ts:37:5 - error TS2615: Type of property 'AND' circularly references itself in mapped type '{ [K in keyof { AND?: UserScalarWhereWithAggregatesInput[]; OR?: UserScalarWhereWithAggregatesInput[]; NOT?: UserScalarWhereWithAggregatesInput[]; id?: IntWithAggregatesFilter; name?: StringWithAggregatesFilter; profile?: JsonWithAggregatesFilter; }]: Or<...> extends 1 ? { ...; }[K] extends infer TK ? GetHavingField...'.
37 this.prismaService.user.groupBy(group);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/users/users.resolver.ts:37:5 - error TS2615: Type of property 'NOT' circularly references itself in mapped type '{ [K in keyof { AND?: UserScalarWhereWithAggregatesInput[]; OR?: UserScalarWhereWithAggregatesInput[]; NOT?: UserScalarWhereWithAggregatesInput[]; id?: IntWithAggregatesFilter; name?: StringWithAggregatesFilter; profile?: JsonWithAggregatesFilter; }]: Or<...> extends 1 ? { ...; }[K] extends infer TK ? GetHavingField...'.
37 this.prismaService.user.groupBy(group);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/users/users.resolver.ts:37:5 - error TS2615: Type of property 'OR' circularly references itself in mapped type '{ [K in keyof { AND?: UserScalarWhereWithAggregatesInput[]; OR?: UserScalarWhereWithAggregatesInput[]; NOT?: UserScalarWhereWithAggregatesInput[]; id?: IntWithAggregatesFilter; name?: StringWithAggregatesFilter; profile?: JsonWithAggregatesFilter; }]: Or<...> extends 1 ? { ...; }[K] extends infer TK ? GetHavingField...'.
37 this.prismaService.user.groupBy(group);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/users/users.resolver.ts:37:37 - error TS2345: Argument of type 'UserGroupByArgs' is not assignable to parameter of type '{ where?: UserWhereInput; orderBy?: UserOrderByWithAggregationInput[]; by: UserScalarFieldEnum[]; having?: UserScalarWhereWithAggregatesInput; ... 6 more ...; _max?: UserMaxAggregateInput; } & { ...; } & (`Error: Field "${any}" used in "having" needs to be provided in "by".` | [...])'.
Type 'UserGroupByArgs' is not assignable to type '{ where?: UserWhereInput; orderBy?: UserOrderByWithAggregationInput[]; by: UserScalarFieldEnum[]; having?: UserScalarWhereWithAggregatesInput; ... 6 more ...; _max?: UserMaxAggregateInput; } & { ...; } & [...]'.
Type 'UserGroupByArgs' is not assignable to type '{ orderBy: Enumerable<UserOrderByWithAggregationInput>; }'.
Property 'orderBy' is optional in type 'UserGroupByArgs' but required in type '{ orderBy: Enumerable<UserOrderByWithAggregationInput>; }'.
37 this.prismaService.user.groupBy(group);
~~~~~
[00:22:13] Found 4 errors. Watching for file changes.
Environment
"@prisma/client": "^2.23.0", "prisma": "^2.23.0", "prisma-nestjs-graphql": "^12.0.0", "@nestjs/common": "^7.6.17", "@nestjs/core": "^7.6.17", "@nestjs/graphql": "^7.10.6",
They are compatible in terms of assignment:
{
const x: UserGroupByArgs = {
by: [UserScalarFieldEnum.id],
};
let p: Prisma.UserGroupByArgs = {
by: [UserScalarFieldEnum.id],
};
p = x; // No Errors
// $prisma.user.groupBy(x); // Error
// $prisma.user.groupBy(p); // Error
}
groupBy method has weird signature
groupBy<
T extends UserGroupByArgs,
HasSelectOrTake extends Or<
Extends<'skip', Keys<T>>,
Extends<'take', Keys<T>>
>,
OrderByArg extends True extends HasSelectOrTake
? { orderBy: UserGroupByArgs['orderBy'] }
: { orderBy?: UserGroupByArgs['orderBy'] },
OrderFields extends ExcludeUnderscoreKeys<Keys<MaybeTupleToUnion<T['orderBy']>>>,
ByFields extends TupleToUnion<T['by']>,
ByValid extends Has<ByFields, OrderFields>,
HavingFields extends GetHavingFields<T['having']>,
HavingValid extends Has<ByFields, HavingFields>,
ByEmpty extends T['by'] extends never[] ? True : False,
InputErrors extends ByEmpty extends True
? `Error: "by" must not be empty.`
: HavingValid extends False
? {
[P in HavingFields]: P extends ByFields
? never
: P extends string
? `Error: Field "${P}" used in "having" needs to be provided in "by".`
: [
Error,
'Field ',
P,
` in "having" needs to be provided in "by"`,
]
}[HavingFields]
: 'take' extends Keys<T>
? 'orderBy' extends Keys<T>
? ByValid extends True
? {}
: {
[P in OrderFields]: P extends ByFields
? never
: `Error: Field "${P}" in "orderBy" needs to be provided in "by"`
}[OrderFields]
: 'Error: If you provide "take", you also need to provide "orderBy"'
: 'skip' extends Keys<T>
? 'orderBy' extends Keys<T>
? ByValid extends True
? {}
: {
[P in OrderFields]: P extends ByFields
? never
: `Error: Field "${P}" in "orderBy" needs to be provided in "by"`
}[OrderFields]
: 'Error: If you provide "skip", you also need to provide "orderBy"'
: ByValid extends True
? {}
: {
[P in OrderFields]: P extends ByFields
? never
: `Error: Field "${P}" in "orderBy" needs to be provided in "by"`
}[OrderFields]
>(args: SubsetIntersection<T, UserGroupByArgs, OrderByArg> & InputErrors): {} extends InputErrors ? GetUserGroupByPayload<T> : Promise<InputErrors>
And as showed above does not compatible with types by prisma
const p: Prisma.UserGroupByArgs = {
by: ['id'],
};
$prisma.user.groupBy(p); // Error
Looks like a bug of prisma
Thanks, I will try to create an issue on prisma side and pray for the best
I was going to create also, If you create, drop here a link
@unlight here prisma/prisma#7183
Workaround is obvious: disable type check by @ts-ignore or by converting to any type, or make explicit type coercion:
type UserGroupBy = Parameters<typeof $prisma.user.groupBy>[0];
const x: UserGroupByArgs = {
by: [UserScalarFieldEnum.id],
};
let p: Prisma.UserGroupByArgs = {
by: [UserScalarFieldEnum.id],
};
$prisma.user.groupBy(p as GroupBy); // No Error
$prisma.user.groupBy(x as GroupBy); // No Error