typescript - Använd Prisma-genererade typer som funktionens parameter-typ
Jag testar Prisma ORM för att se vilka möjligheterna är. Efter att ha skapat modellerna och genererat PrismaClient trodde jag att det skulle vara möjligt att använda de genererade typerna och använda dem för variabler och responstyper, men det verkar inte vara fallet.
...
model Invite {
id Int @id @default(autoincrement())
gender Gender
firstName String @map("first_name")
lastName String @map("last_name")
language Language
email String @unique
token String @unique
roleId Int @map("role_id")
role Role @relation(fields: [roleId], references: [id])
organisationId Int @map("organisation_id")
organisation Organisation @relation(fields: [organisationId], references: [id])
updatedAt DateTime @updatedAt @map("updated_at")
createdAt DateTime @default(now()) @map("created_at")
@@map("invites")
}
...
Ovan har jag en Invite-modell med en relation till organisation- och rollmodellerna. I en invite-tjänstfil förbereder jag all input för att skapa en ny invite.
import { Request, Response, NextFunction } from 'express';
import roleRepository from '../repositories/role.repository';
import organisationRepository from '../repositories/organisation.repository';
import generateToken from '../utils/helpers/generateToken';
import inviteRepository from '../repositories/invite.repository';
const createInvite = async (req: Request, res: Response) => {
const { body } = await validateInput(req);
const { gender, firstName, lastName, email, language, roleId, organisationId } = body;
const role = roleRepository.findRoleById(roleId);
if (!role) {
throw new Error('Role does not exist');
}
const organisation = organisationRepository.findOrganisationById(organisationId);
if (!organisation) {
throw new Error('Organisation does not exist');
}
const token = generateToken();
const invite = inviteRepository.createInvite({
gender,
firstName,
lastName,
email,
language,
role: role,
organisation: organisation,
token,
});
await mailService.sendInviteEmail(invite);
res.status(201).json({
message: 'Invite created successfully',
});
};
I createInvite-funktionen i inviteRepository-filen försöker jag använda en genererad typ från Prisma, InviteCreateInput.
const createInvite = async (inviteData: Prisma.InviteCreateInput): Promise<Invite> => {
return db.invite.create({
data: {
gender: inviteData.gender,
firstName: inviteData.firstName,
lastName: inviteData.lastName,
language: inviteData.language,
email: inviteData.email,
token: inviteData.token,
role: {
connect: {
id: inviteData.role
}
},
organisation: {
connect: {
id: inviteData.organisation,
}
}
},
});
};
Prisma rekommenderar detta 'säkra' sätt att mata in data men InviteCreateInput ser ut så här
export type InviteCreateInput = {
gender: Gender
firstName: string
lastName: string
language: string
email: string
token: string
updatedAt?: Date | string
createdAt?: Date | string
role: RoleCreateNestedOneWithoutInviteInput
organisation: OrganisationCreateNestedOneWithoutInvitesInput
}
och RoleCreateNestedOneWithoutInviteInput ser ut så här:
export type RoleCreateNestedOneWithoutInviteInput = {
create?: XOR<RoleCreateWithoutInviteInput, RoleUncheckedCreateWithoutInviteInput>
connectOrCreate?: RoleCreateOrConnectWithoutInviteInput
connect?: RoleWhereUniqueInput
}
Eftersom denna typ förväntar sig en create, connectOrCreate eller connect verkar den vara oanvändbar som funktionsparametertyp för denna funktion (Jag undrar också i vilken situation denna typ skulle kunna vara användbar). Jag hittade InviteUncheckedCreateInput som en möjlig typ att använda men eftersom Prisma inte rekommenderar att använda unchecked-typerna är jag inte säker på om detta är en bra metod.
Någon med erfarenhet av att använda Prisma-typer som typparameter för funktioner eller är det bättre att skapa en typ själv?
Svar #1
Anledningen till att Prisma föreslår att det är "säkrare" är eftersom de antar att du kanske inte kontrollerar roleId eller organisationId (vilket du gör med findRoleById och findOrganisationById).
För prestanda skulle jag ta bort de extra frågorna - findRoleById och findOrganisationById och skriva din middleware så här:
const createInvite = async (req: Request, res: Response) => {
const { body } = await validateInput(req);
const { gender, firstName, lastName, email, language, roleId, organisationId } = body;
const token = generateToken();
try {
const invite = await inviteRepository.createInvite({
gender,
firstName,
lastName,
email,
language,
token,
role: {
connect: {
id: roleId,
},
},
organisation: {
connect: {
id: organisationId,
},
},
});
} catch (error) {
// handle the errors from no organisationId nor roleId existing
// next(Error) or something similar
}
await mailService.sendInviteEmail(invite);
res.status(201).json({
message: 'Invite created successfully',
});
};
Du kan också rengöra din createInvite-funktion:
const createInvite = async (data: Prisma.InviteCreateInput): Promise<Invite> => {
return db.invite.create({
data,
});
};
