Skip to content

feat!: upgrade to Zod 4#163

Merged
chmaltsp merged 10 commits intomainfrom
claude/upgrade-zod-4-BiELX
Jan 12, 2026
Merged

feat!: upgrade to Zod 4#163
chmaltsp merged 10 commits intomainfrom
claude/upgrade-zod-4-BiELX

Conversation

@chmaltsp
Copy link
Copy Markdown
Contributor

@chmaltsp chmaltsp commented Jan 9, 2026

Summary

  • Upgrades Zod peer dependency to support both v3 and v4 (^3.0.0 || ^4.0.0)
  • Adds compatibility layer to handle Zod v3/v4 internal API differences
  • Updates OpenAPI generation to work with Zod 4's new schema structure

Breaking Change

This is a major version bump. While the package supports both Zod 3 and Zod 4, users on Zod 3 should test thoroughly before upgrading.

Zod 4 Internal API Changes Handled

  • Schema definitions moved from ._def to ._zod.def
  • Type names changed from _def.typeName to constructor names ($ZodStringZodString)
  • Literal values stored in def.values array instead of def.value
  • String/number checks store properties in check._zod.def instead of directly on check
  • Enum values accessed via schema.options instead of def.values

Test Plan

  • All existing tests pass
  • OpenAPI generation produces correct output
  • Literal values correctly generate type: "string", enum: ["value"]
  • String constraints (maxLength, minLength, format) work correctly
  • UUID format preserved in generated OpenAPI spec

🤖 Generated with Claude Code

claude and others added 9 commits January 9, 2026 19:25
This update adds support for Zod 4 while maintaining backwards compatibility with Zod 3. Key changes:

- Update peerDependency to support both zod ^3.0.0 and ^4.0.0
- Create zod-compat.ts utility module to abstract internal Zod API differences
- Update with-validation.ts to use compatibility helpers
- Update vendored zod-openapi.ts and zod-to-ts.ts for Zod 4
- Update generate-openapi and generate-route-types for Zod 4 compatibility
- Simplify type definitions to work with both Zod versions
- Remove unused @anatine/zod-openapi dependency (code was already vendored)

Breaking changes in Zod 4 that were addressed:
- ._def moved to ._zod.def
- ._def.typeName moved to ._zod.def.type
- ZodEffects and ZodObject type signatures changed
- Various class exports renamed or removed
…patibility

Zod 4 has stricter type inference than Zod 3. The jsonResponse schema
was defining todo as required, but the handler returns without todo
when ok=false. This caused TypeScript errors with Zod 4's improved
type inference.

- Make todo optional in get.ts and index.ts response schemas
- Remove .failing modifier from get-boolean test since it now passes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
In Zod 4, the shape property is accessed differently via the def object.
Use the getShape helper from zod-compat instead of accessing .shape directly.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update getEnumValues to handle Zod 4's different enum structure
  (uses schema.options/enum instead of def.values)
- Update parseString to handle Zod 4's check format
  (uses item.format/item.def.check instead of item.kind)
- Update tests to use t.like for flexibility with Zod 4's extra properties
- Update error message assertions to handle Zod 4's different format

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove @ts-nocheck and fix type errors properly
- Replace ts-deepmerge with simple Object.assign (deep merge not needed
  for flat metadata)
- Add ExtendedSchemaObject type for OpenAPI 3.0 nullable compatibility
- Fix ZodObject generic parameters for Zod 3/4 compatibility
- Fix discriminator null check
- Use ZodTypeAny instead of ZodLiteral generic for compatibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
No longer needed since we use simple Object.assign for merging.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix getLiteralValue to use schema.value or def.values[0] for Zod 4
- Fix getChecks to normalize Zod 4 check objects by flattening _zod.def
- Simplify parseString to use normalized check properties

Zod 4 stores literal values in def.values (array) instead of def.value,
and string checks have properties in check._zod.def instead of directly
on the check object.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chmaltsp chmaltsp changed the title Upgrade to Zod 4 feat!: upgrade to Zod 4 Jan 10, 2026
BREAKING CHANGE: This release upgrades the Zod peer dependency from v3 to v4.
Users must upgrade their Zod dependency to ^4.0.0 to use this version.

Zod 4 has internal API changes that required updates to the compatibility layer:
- Schema definitions moved from ._def to ._zod.def
- Literal values stored in def.values array instead of def.value
- Check objects store properties in check._zod.def

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chmaltsp chmaltsp merged commit d829b41 into main Jan 12, 2026
2 checks passed
github-actions bot pushed a commit that referenced this pull request Jan 15, 2026
# [3.0.0](v2.20.0...v3.0.0) (2026-01-15)

* feat!: upgrade to Zod 4 (#163) ([d829b41](d829b41)), closes [#163](#163)

### BREAKING CHANGES

* This release upgrades the Zod peer dependency from v3 to v4.
Users must upgrade their Zod dependency to ^4.0.0 to use this version.

Zod 4 has internal API changes that required updates to the compatibility layer:
- Schema definitions moved from ._def to ._zod.def
- Literal values stored in def.values array instead of def.value
- Check objects store properties in check._zod.def

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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.

2 participants