Skip to content

Optional properties become required in inferred Zod v4 schema types #1362

@Charl13

Description

@Charl13

Issue description

When generating Zod v4 schemas with this plugin, optional properties are inferred as required in the resulting TypeScript type. This is caused by the use of Required in the Properties<T> type definition, which marks all fields as required, even if
they are optional in the original schema.

Generated code

type Properties<T> = Required<{
  [K in keyof T]: z.ZodType<T[K], T[K]>
}>

export function EmployeeDocumentSchema(): z.ZodObject<Properties<EmployeeDocument>> {
  return z.object({
    __typename: z.literal('EmployeeDocument').optional(),
    _id: z.number().int(),
    id: z.string(),
    expireDate: z.string().nullish(),
    mimeType: z.string(),
    name: z.string(),
    rejectionReason: z.string().nullish(),
    status: z.number().int()
  })
}

Implementation

type EmployeeDocumentType = z.infer<typeof EmployeeDocumentSchema>

// All properties are now required, even the optional ones!
// {
//   __typename: 'EmployeeDocument' | undefined,
//   _id: int,
//   id: string,
//   expireDate: string | null |undefined,
//   mimeType: string,
//   name: string,
//   rejectionReason: string | null | undefined,
//   status: int,
// }

Expected behavior:

Optional fields in should also be optional in the inferred Zod type (not just type undefined added).

Implementation

const EmployeeDocumentSchema = z.object({
  __typename: z.literal('EmployeeDocument').optional(),
  _id: z.number().int(),
  expireDate: z.string().nullish(),
  id: z.string(),
  mimeType: z.string(),
  name: z.string(),
  rejectionReason: z.string().nullish(),
  status: z.number().int()
})

type EmployeeDocumentSchema = z.infer<typeof EmployeeDocumentSchema>

// Field like __typename, expireDate and rejectionReason are optional!
// {
//   __typename?: 'EmployeeDocument' | undefined,
//   _id: int,
//   id: string,
//   expireDate?: string | null |undefined,
//   mimeType: string,
//   name: string,
//   rejectionReason?: string | null | undefined,
//   status: int,
// }

See also: https://github.com/Code-Hex/graphql-codegen-typescript-validation-schema/tree/main/example/zodv4

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions