-
Notifications
You must be signed in to change notification settings - Fork 6
Add zod/v4 Support to TypeMap
#34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
@theshadow27 Hi, this PR is a amazing work, thank you! So going through, everything looks good to me, again excellent work! I have left a couple of comments on the TypeMap leans heavily on having runtime and type mapping logic aligned as closely as possible (they should be identical if possible). As a general rule, runtime logic should only be implemented if that same logic can be expressed in the type system (where the type system implementation usually dictates the runtime implementation). Just have a quick look a see if it's possible to express this logic using This PR looks great and would be happy to merge in with the above changes. Do you think it would it be worthwhile including a Let me know your thoughts on the above. Again, nice work, this one will be good to merge :) |
|
Hi @sinclairzx81 — thanks for the quick turnaround and the detailed notes.
I don’t see inline comments in the GitHub UI yet—maybe the review wasn’t submitted? Assuming you’re referring to the string-format converter, yeah, it didn't sit well, but it was 2AM 🤣 . I’ve since re-worked it to The only wrinkle is that Zod v4 holds sets of regexes for certain formats, while I could only find a single If TypeBox has a recommended pattern-combining helper I missed, let me know! The only other option I can think of is to return it as an intersection (
Regardless, it's worth noting that the assumption of "one pattern" string was also present in the original EXTRA_TESTING=true npm run testv3 with extra tests (9 failures)String Validation Behavior
Basic String Checks
✔ Should validate startsWith correctly
✔ Should validate endsWith correctly
1) Should validate includes correctly 🚨
2) Should validate regex patterns correctly 🚨
Combined String Checks
✔ Should validate startsWith + endsWith correctly
3) Should validate startsWith + includes correctly 🚨
4) Should validate endsWith + includes correctly 🚨
5) Should validate startsWith + endsWith + includes correctly 🚨
Special Case Combinations
✔ Should validate ipv4 with startsWith correctly
6) Should validate regex with startsWith correctly 🚨
✔ Should validate email with endsWith correctly
Edge Cases
✔ Should handle empty string checks correctly
7) Should handle special regex characters in string checks 🚨
8) Should handle conflicting constraints 🚨
Format and Constraint Combinations
✔ Should combine format with length constraints
✔ Should combine format with pattern constraints
9) Should handle multiple constraints on formats 🚨V4 with extra tests (3 failures)the little regex hack I put together does make a number of these pass, but not perfect... String Validation Behavior
Basic String Checks
✔ Should validate startsWith correctly
✔ Should validate endsWith correctly
10) Should validate includes correctly 🚨
11) Should validate regex patterns correctly 🚨
✔ Should validate lowercase correctly
✔ Should validate uppercase correctly
Combined String Checks
✔ Should validate startsWith + endsWith correctly
✔ Should validate startsWith + includes correctly
✔ Should validate endsWith + includes correctly
✔ Should validate startsWith + endsWith + includes correctly
Special Case Combinations
✔ Should validate ipv4 with startsWith correctly
12) Should validate regex with startsWith correctly 🚨
✔ Should validate email with endsWith correctly
Edge Cases
✔ Should handle empty string checks correctly
✔ Should handle special regex characters in string checks
✔ Should handle conflicting constraints
Format and Constraint Combinations
✔ Should combine format with length constraints
✔ Should combine format with pattern constraints
✔ Should handle multiple constraints on formatsI don't think there's actually a way to accurately and arbitrarily combine regex strings into a single pattern (as required by TypeBox and JsonSchema). So either, we leave it alone with a warning, or look into automatic intersections. Let me know what you think!
I started with the goal of complete symmetry (and do very much admire the beauty of such things), but the divergence between v3 and v4 (especially around I agree there’s real value in one-hop However, I think it would be possible to stub in a That way, in the future, a direct one-hop conversion would not change the API. Are you OK with a quick stub and a follow-on for the direct conversion? I’m happy to do the stub and brainstorm on the direct conversion in a different thread, if that is ok with you. Appreciate the feedback—and thanks for maintaining such a well-structured codebase. 🙌 |
|
@sinclairzx81 - FYI I've added the 2-hop conversion, so now the API is fully symmetrical (again). PS. I've been chewing on the idea of a universal type+validation system for a while, and what you've built here is real art. |
|
Ugh, it seems my excitement was to be short lived. Once I used it in anger (real project), started seeing lots of dropped types. Went back and checked, copilot had straight up dropped the hard ones 😆 😭 so back to doing it old school. I did some hand-coding, and it's now much closer to what it should have been the first time. @sinclairzx81 Please check the new zod4-tsc-tests.ts, specifically:
Sorry and thanks! |
|
Hi @sinclairnick @sinclairzx81, Any guidance on how I can get the TemplateLiteral and Union adapters working? Would greatly appreciate TypeBox creator 🧠... Thanks again for your time! jd |
|
Hey, thank you for working on this! Are there any plans on this PR being pushed forward? |

PR: Add Zod v4 Support to TypeMap
TL;DR
This PR introduces first-class support for Zod v4 schemas while preserving full compatibility with existing Zod v3 functionality.
All core converters, guards, compile paths, and tests now understand v4.
Remaining work is limited to a few low-level API deltas and edge-case tests (see Future Work).
Motivation
Zod v4 breaks API parity with v3 (e.g. top-level string validators, new error maps,
defvs_def, strict/loose objects).Consumers who have already migrated to v4 need TypeMap to round-trip those schemas to and from Syntax, TypeBox, and Valibot. This PR delivers that capability without forcing v3 users to upgrade.
High-Level Changes
/src/zod4/namespace with a drop-inZod4builder and bidirectional converters.IsZod4detection (checks~standard.vendor === 'zod'anddef/metamarkers). Refactored common vendor logic.index.tsre-export now includes all Zod4 artefacts (TZod4,Zod4FromTypeBox, …).typebox-from-zod4andzod4-from-typeboxround-trip tests•
zod-detection-testcovering v3 vs v4 heuristicszodas a peer with^3.25.0(the first tag that contains the/v4export path). No new dependencies added, beyond the version bump.Detailed Implementation Notes
Core Builder (
/src/zod4/zod4.ts)import { z } from 'zod/v4'and exposesZod4/TZod4.Converter Matrix
/src/{syntax,typebox,valibot}/…-from-zod4.tsand/src/zod4/zod4-from-*.ts.Version Detection
Ensures mixed-version projects resolve the correct converter without false positives.
Top-Level String & IP Validators
z.email()etc. map to their v3 equivalents for cross-conversion.base64, base64url, cidrv4, cidrv6, cuid, cuid2, date,
datetime, duration, e164, email, emoji, guid, ipv4, ipv6,
json_string, jwt, ksuid, lowercase, nanoid, time, ulid, uppercase, url, uuid, xid
Backward Compatibility
import * as z from 'zod'paths; detection logic chooses v3 converters.Performance
Re-ran the benchmarks with z4 support. Key takeaways:
Future Work (out of scope)
API deltas
z.strictObject/z.looseObjectz.nonoptional()/z.prefault()Edge-Case Tests
test/parameters-zod4.ts)E2E Matrix
Checklist
npm test)package.jsonafter mergeReady for review. Please focus on:
IsZod4)cc: @typemap-maintainers @sinclairzx81 @colinhacks