This is my first ever TypeScript project and I am using Fastify and Prisma to build it. I have extensively searched for this error and it's not a generic one. Similar questions were not helpful to my case. I am working on a User table where I have the prisma.schema as:
model User {
id Int @id @default(autoincrement())
firstName String
lastName String
email String @unique
phone String @unique
room Room? @relation(fields: [roomId], references: [id])
roomId Int?
utilities Utility[]
rentStatus Boolean?
amountDue Float?
dateSigned DateTime?
dateLeft DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
I have a user.schema.ts that contains the Zod schema for validation:
import { z } from 'zod'
const createUserSchema = z.object({
firstName: z.string({
required_error: "First name is required"
}),
lastName: z.string({
required_error: "Last name is required"
}),
email: z.string({
required_error: "Email is required",
invalid_type_error: "Email must be a string"
}).email(),
phone: z.string({
required_error: "Phone number is required"
})
});
export type CreateUserInput = z.infer<typeof createUserSchema>
In my user.service.ts I have this setup:
import prisma from "../utils/prisma";
import { CreateUserInput } from "./user.schema";
export async function createUser(input: CreateUserInput) {
const user = await prisma.user.create({
data: input
});
}
But "data" is errored out with this:
(property) data: (Prisma.Without<Prisma.UserCreateInput, Prisma.UserUncheckedCreateInput> & Prisma.UserUncheckedCreateInput) | (Prisma.Without<Prisma.UserUncheckedCreateInput, Prisma.UserCreateInput> & Prisma.UserCreateInput)
The data needed to create a User.
Type '{ firstName?: string; lastName?: string; email?: string; phone?: string; }' is not assignable to type '(Without<UserCreateInput, UserUncheckedCreateInput> & UserUncheckedCreateInput) | (Without<...> & UserCreateInput)'.
Type '{ firstName?: string; lastName?: string; email?: string; phone?: string; }' is not assignable to type 'Without<UserUncheckedCreateInput, UserCreateInput> & UserCreateInput'.
Type '{ firstName?: string; lastName?: string; email?: string; phone?: string; }' is not assignable to type 'UserCreateInput'.
Property 'firstName' is optional in type '{ firstName?: string; lastName?: string; email?: string; phone?: string; }' but required in type 'UserCreateInput'.ts(2322)
index.d.ts(1911, 5): The expected type comes from property 'data' which is declared here on type '{ select?: UserSelect; include?: UserInclude; data: (Without<UserCreateInput,UserUncheckedCreateInput> & UserUncheckedCreateInput) | (Without<...> & UserCreateInput); }'
Unfortunately, I cannot make sense of this error. One thing that stands out though is it complaining about firstName, lastName, email and phone being optional. But I have set it as required both in Zod and Prisma. It seems like I am missing something very trivial here.
CodePudding user response:
Whatever your user.schema
file is, it is emitting a type CreateUserInput
which lists all the properties of a User
as optional. That is incompatible with Prisma's expected type for await prisma.user.create
which expects some fields which are required. Because you are passing in input
which has type CreateUserInput
, Prisma thinks all those fields are optional. Your error lies in why CreateUserInput
has its fields listed as optional, which seems to be something to do with z.infer
CodePudding user response:
Thanks to @Shea I was able to narrow down the issue. Looks like Zod was creating optional fields for firstName, lastName, email and phone, even though I did not have them set to optional. The fix was adding "strict":
true in tsconfig.json
under "compilerOptions"
.