Home > other >  Typescript error with Zod and Prisma Schema
Typescript error with Zod and Prisma Schema

Time:09-03

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".

  • Related