I'm working with Prisma to make a generic repository object. Here's my current interface (which the base repository implements) which works:
import { Log as LogSchema, Prisma, User as UserSchema } from "@prisma/client";
import type { CamelCase } from "type-fest";
type PrismaSchema = UserSchema | LogSchema; // I currently have to define all schemas schema.prisma here
type NonWriteable = "updatedAt" | "createdAt"; // I also have to explicitly define fields which should never be writeable
type WriteableSchemaWithId<Schema> = Omit<Schema, NonWriteable>;
type WriteableSchema<Schema> = Omit<WriteableSchemaWithId<Schema>, "id">;
interface IBaseRepository<
Key extends CamelCase<Prisma.ModelName>,
Schema extends PrismaSchema
> {
create: (parameters: { [key in Key]: WriteableSchema<Schema> }) => Promise<{
id: number;
}>;
// ... Other methods
}
However, in the type of argument to the create
method are slightly incorrect. I'd really be like to using the Prisma-generated types instead of the type of the schema. For example, the Prisma client exports UserCreateArgs
which defines what can be passed to prisma.user.create({ data: ... })
.
Then I'd have to do this for all actions, for all schemas. Now, this isn't a problem currently because there are only two models with no relations to each other. However, I'm expecting this implementation to become brittle (and cumbersome) with a more complex database schema.
Instead, I was looking for something like:
import { Prisma } from "@prisma/client";
import type { PascalCase } from "type-fest";
type NamespaceKey<
Model extends Prisma.ModelName,
Action extends Prisma.PrismaAction
> = `${Capitalize<Model>}${PascalCase<Action>}Args`;
type ActionArgs<
Model extends Prisma.ModelName,
Action extends Prisma.PrismaAction
> = typeof Prisma[NamespaceKey<Model, Action>];
Where NamespaceKey
turns User
into e.g., UserCreateArgs
which should be imported from the Prisma namespace.
But I get an error saying NamespaceKey
cannot be used to index typeof Prisma
.
Is there a way to get what I'm looking for?
Edit:
The problem seems to revolve around the inability to string-index types in a namespace.
For example, Prisma["ModelName"]
works as the following is exported:
export const ModelName: {
User: 'User',
Log: 'Log'
};
Along with the type:
export type ModelName = (typeof ModelName)[keyof typeof ModelName]
However, Prisma["UserCreateArgs"]
does not seem to exist since UserCreateArgs
is a type.
So, it seems like it is not possible to string-index the types defined in a namespace. If this were possible, one would assume what I have already would work.