I implemented such class:
import { PrismaClient } from '@prisma/client';
export type NotStartsWith<
S,
Prefix extends string,
> = S extends `${Prefix}${infer _X}` ? never : S;
export class DatabaseService extends PrismaClient {
async $findPaginated<
M extends NotStartsWith<keyof DatabaseService, '$'>,
A extends Parameters<DatabaseService[M]['findMany']>[0],
>(model: M, args?: A) {
const data = await this[model].findMany(args);
return {
page: 1,
results: data,
total: 1,
totalPages: 1,
};
}
}
Let's assume I have models post and user.
The real implementation is not important. But typescript gives me this error on the findMany call:
This expression is not callable. Each member of the union type 'x | y | z' has signatures, but none of those signatures are compatible with each other.
I think it means that somehow I could call the findMany of user with arguments of post. But it is not possible since it is all well typed. If I change to (this[model] as any) to compile and type my new function with first argument post, the second argument's properties are correctly autocompleted for the model post.
So I don't get why I can't fully type my function.
Also, this is not an optimal extension for Prisma. Ideally I'd like to add typings to a very generic interface (findMany, findUnique etc.) that all models' use, and then add my function to all models at runtime. But that's not how Prisma generate types.