zod-prisma-types
zod-prisma-types copied to clipboard
Types mismatch between the generated zod types and the prisma client types
zod-prisma-types generates a schema for a field missing in the prisma generated types
"@prisma/client": "4.11.0",
"zod-prisma-types": "2.4.0"
The Prisma schema
generator client {
provider = "prisma-client-js"
}
generator zod {
provider = "zod-prisma-types"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Account {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
countryCode String?
countryName String?
currencyCode String @default("USD")
isOnboarded Boolean @default(false)
user User[]
contact Contact[]
}
model User {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime? @updatedAt
email String @unique
name String?
language String @default("en")
locale String @default("en-US")
contact Contact[]
role Role[] @default([ADMIN])
account Account @relation(fields: [accountId], references: [id])
accountId String
}
enum Role {
ADMIN
}
model Contact {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
contactType ContactType @default(OTHER)
firstName String
lastName String
businessName String?
displayName String?
isBusiness Boolean @default(false)
phone Phone[]
email Email[]
address Address[]
user User[]
account Account @relation(fields: [accountId], references: [id])
accountId String
}
enum ContactType {
OTHER
}
model Phone {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
number String
isPrimary Boolean @default(false)
contact Contact @relation(fields: [contactId], references: [id])
contactId String
}
model Email {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
email String
isPrimary Boolean @default(false)
contact Contact @relation(fields: [contactId], references: [id])
contactId String
}
model Address {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
line1 String
line2 String?
city String
state String?
region String?
zip String
country String
formatted String?
contact Contact @relation(fields: [contactId], references: [id])
contactId String
}
the generated zod type having an error
export const ContactCreateWithoutUserInputSchema: z.ZodType<Prisma.ContactCreateWithoutUserInput> = z.object({
id: z.string().optional(),
createdAt: z.coerce.date().optional(),
updatedAt: z.coerce.date().optional(),
contactType: z.lazy(() => ContactTypeSchema).optional(),
firstName: z.string(),
lastName: z.string(),
businessName: z.string().optional().nullable(),
displayName: z.string().optional().nullable(),
isBusiness: z.boolean().optional(),
phone: z.lazy(() => PhoneCreateNestedManyWithoutContactInputSchema).optional(),
email: z.lazy(() => EmailCreateNestedManyWithoutContactInputSchema).optional(),
address: z.lazy(() => AddressCreateNestedManyWithoutContactInputSchema).optional(),
account: z.lazy(() => AccountCreateNestedOneWithoutContactInputSchema),
}).strict();
export const ContactUncheckedCreateWithoutUserInputSchema: z.ZodType<Prisma.ContactUncheckedCreateWithoutUserInput> = z.object({
id: z.string().optional(),
createdAt: z.coerce.date().optional(),
updatedAt: z.coerce.date().optional(),
contactType: z.lazy(() => ContactTypeSchema).optional(),
firstName: z.string(),
lastName: z.string(),
businessName: z.string().optional().nullable(),
displayName: z.string().optional().nullable(),
isBusiness: z.boolean().optional(),
accountId: z.string(),
phone: z.lazy(() => PhoneUncheckedCreateNestedManyWithoutContactInputSchema).optional(),
email: z.lazy(() => EmailUncheckedCreateNestedManyWithoutContactInputSchema).optional(),
address: z.lazy(() => AddressUncheckedCreateNestedManyWithoutContactInputSchema).optional(),
}).strict();
export const ContactCreateOrConnectWithoutUserInputSchema: z.ZodType<Prisma.ContactCreateOrConnectWithoutUserInput> = z.object({
where: z.lazy(() => ContactWhereUniqueInputSchema),
create: z.union([ z.lazy(() => ContactCreateWithoutUserInputSchema),z.lazy(() => ContactUncheckedCreateWithoutUserInputSchema) ]),
}).strict();
the generated prisma type
export type ContactCreateWithoutUserInput = {
id?: string
createdAt?: Date | string
updatedAt?: Date | string
contactType?: ContactType
firstName: string
lastName: string
businessName?: string | null
displayName?: string | null
isBusiness?: boolean
phone?: PhoneCreateNestedManyWithoutContactInput
email?: EmailCreateNestedManyWithoutContactInput
address?: AddressCreateNestedManyWithoutContactInput
account: AccountCreateNestedOneWithoutContactInput
}
the ts error
Type 'ContactCreateWithoutUserInput & ContactUncheckedCreateWithoutUserInput' is not assignable to type 'Without<ContactUncheckedCreateWithoutUserInput, ContactCreateWithoutUserInput>'.
Types of property 'accountId' are incompatible.
Type 'string' is not assignable to type 'undefined'.ts(2322)`
@atanaskanchev thank's for the report. I'm aware of this issue and currently working on a fix for that. This has to do with an updated Prisma XOR
type that does not accept a simple union anymore.
@atanaskanchev this seems to be a bit of a complex issue. I've started a discussion on the zod page on how this could be resolved.
I rolled back Zod to 3.21.1 from 3.21.2 and that's getting me past this issue.
Opened an issue in the zod repo: https://github.com/colinhacks/zod/issues/2184
I tried rolling back but ran into this error:
Property 'coerce' does not exist on type 'typeof import(\"/path/to/project/node_modules/zod/lib/external\")'.
export const UserSchema = z.object({
id: z.string().cuid(),
name: z.string().nullable(),
email: z.string(),
createdAt: z.coerce.date(),
updatedAt: z.coerce.date(),
})
I rolled back Zod to 3.21.1 from 3.21.2 and that's getting me past this issue.
I was able to get around this as well by rolling back to 3.21.1 from 3.21.4
Since there is no movement on the zod issue I thought of a rude override to enable the use of zod version greater than 3.21.1
:
The simple solution for now would be to just add a type assertion like:
export const UserCreateInputSchema: z.ZodType<Prisma.UserCreateInput> = z.object({ id: z.string().cuid().optional(), email: z.string().email({ message: "Invalid email address" }), name: z.string().min(1).max(100).optional().nullable(), ... }).strict() as z.ZodType<Prisma.UserCreateInput>;
since the schemas work, as confirmd by using zod 3.21,1
there should be little risk that the behavior breaks when using type assertions. But as mentioned above it feels like a dirty hack that hurts my typesafe heart a little bit and that should actually not be needed.
Any thougths on this? should probably be swichable via generator option and off by default.
Rolling back zod to 3.21.1 leads to my project not working any more. The reason is that this project uses uuid v7 and it seems that zod does not recognize uuid v7 as valid until later versions (3.22.4 works). For more info see https://github.com/electric-sql/electric/issues/1153#issuecomment-2055583872
zod 3.23 has been released, and may include a fix for the XOR issue: https://github.com/colinhacks/zod/issues/2184#ref-pullrequest-2254755159