Skip to content

fix: optionality handling in zodv4 Properties type#1521

Open
Dqu1J wants to merge 1 commit into
Code-Hex:mainfrom
Dqu1J:main
Open

fix: optionality handling in zodv4 Properties type#1521
Dqu1J wants to merge 1 commit into
Code-Hex:mainfrom
Dqu1J:main

Conversation

@Dqu1J

@Dqu1J Dqu1J commented Jul 16, 2026

Copy link
Copy Markdown

Issue

With the zodv4 schema the generated schemas fail to typecheck with their optional field types degrading to unknown. The issue is in the Properties type:

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

In Zod v4, z.object determines whether a key is optional by checking the field schema's internal optout flag.
Currently the Properties type defines every field as a plain ZodType, which doesn't have that flag set, so optionality can't be inferred. That causes optional fields to degrade to unknown.

Fix

The Properties type has been changed as follows:

type Properties<T> = Required<{
  [K in keyof T]: undefined extends T[K]
    ? z.ZodType<T[K]> & { _zod: { optout: "optional" } }
    : z.ZodType<T[K]>
}>;

Optional fields (those that can be undefined) get their ZodType intersected with { _zod: { optout: "optional" } }, which sets the optout flag to mark the field as optional to Zod. That lets z.object infer the correct optionality.
Required<> is needed because otherwise the type's ? would be carried over to the schema itself, making it possibly undefined, which breaks z.object's inference and causes the field to degrade to unknown.
While _zod and optout is Zod's internal API, it seems to be stable and recommended to use by maintainers.

Testing

  1. Testing coverage: ran pnpm run test with and without changes, number of passed tests match.
  2. Tested changes on a personal project, 99+ type errors resolved.

Closes #1494
Closes #1460

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

zodv4 output produces unknown for optional nested input fields with exactOptionalPropertyTypes: true Invalid types generated

1 participant