Zod 4 support: fix VUnion<… …[]> handling in convexToZod#872
Zod 4 support: fix VUnion<… …[]> handling in convexToZod#872
VUnion<… …[]> handling in convexToZod#872Conversation
📝 WalkthroughWalkthroughThe changes extend the convexToZod converter to properly handle multi-member union validators (VUnion with 2+ members), addressing incompatibility with the literals helper. Two regression tests validate correct behavior. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
commit: |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/convex-helpers/server/zod4.ts (2)
943-964:⚠️ Potential issue | 🔴 CriticalSame
readonlyconstraint issue exists inZodFromStringValidator.This branch mirrors the one in
ZodFromValidatorBaseand will have the same type error once the compiler reaches it. Apply the samereadonlyremoval fix here.Proposed fix
: V extends VUnion< any, - infer Members extends readonly [ + infer Members extends [ GenericValidator, GenericValidator, ...GenericValidator[], ], any, any >🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/convex-helpers/server/zod4.ts` around lines 943 - 964, The ZodFromStringValidator branch carries the same readonly tuple constraint that causes the type error; open the ZodFromStringValidator declaration and remove the readonly modifiers from the tuple/generic constraint (make [] | [Record<string, any>] mutable, matching the fix applied to ZodFromValidatorBase) so the ArgsForHandlerType-style merging works; ensure the tuple/generic signatures and any inferred tuple types in ZodFromStringValidator mirror the non-readonly form used in ZodFromValidatorBase (no other behavioral changes).
880-905:⚠️ Potential issue | 🔴 CriticalFix type constraint errors in VUnion type mappings at lines 1880–1910 and 1930–1965.
The TypeScript type checker reports indexing errors in two locations where
Members(a tuple type) is processed with a filtered mapped type:packages/convex-helpers/server/zod4.ts(1873,37): error TS2574: A rest element type must be an array type. packages/convex-helpers/server/zod4.ts(1894,42): error TS2536: Type 'Exclude<keyof Members, "0" | "1">' cannot be used to index type '{...}'. packages/convex-helpers/server/zod4.ts(1938,21): error TS2574: A rest element type must be an array type. packages/convex-helpers/server/zod4.ts(1957,26): error TS2536: Type 'Exclude<keyof Members, "0" | "1">' cannot be used to index type '{...}'.The issue is with the mapped-type approach that filters out indices
"0"and"1":...{ [K in keyof Members as K extends "0" | "1" ? never : K]: ZodValidatorFromConvex<Members[K]>; }[Exclude<keyof Members, "0" | "1">][]This pattern produces an object type, not an array. The mapped type with an
asclause filters keys but creates an incompatible type for the rest spread operator and subsequent indexing. Consider using a recursive utility type or conditional-type approach (similar toConvexUnionValidatorFromZodMembers) that directly recurses over remaining tuple elements instead of relying on mapped-type filtering.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/convex-helpers/server/zod4.ts` around lines 880 - 905, The VUnion type mapping is producing an object type (and causing TS2574/TS2536 errors) because the mapped-type trick that filters keys ("0" | "1") yields an object, not an array; replace that mapped-type with a recursive conditional tuple utility that walks the Members tuple and builds an array of ZodValidatorFromConvex<...> for the remaining elements (similar to how ConvexUnionValidatorFromZodMembers recurses), and then use that recursive result for indexing/rest operations; update the type aliases that reference Members and ZodValidatorFromConvex (and any uses in VUnion) to use the new recursive utility so the compiler sees an actual array/tuple type rather than an object.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@packages/convex-helpers/server/zod4.ts`:
- Around line 943-964: The ZodFromStringValidator branch carries the same
readonly tuple constraint that causes the type error; open the
ZodFromStringValidator declaration and remove the readonly modifiers from the
tuple/generic constraint (make [] | [Record<string, any>] mutable, matching the
fix applied to ZodFromValidatorBase) so the ArgsForHandlerType-style merging
works; ensure the tuple/generic signatures and any inferred tuple types in
ZodFromStringValidator mirror the non-readonly form used in ZodFromValidatorBase
(no other behavioral changes).
- Around line 880-905: The VUnion type mapping is producing an object type (and
causing TS2574/TS2536 errors) because the mapped-type trick that filters keys
("0" | "1") yields an object, not an array; replace that mapped-type with a
recursive conditional tuple utility that walks the Members tuple and builds an
array of ZodValidatorFromConvex<...> for the remaining elements (similar to how
ConvexUnionValidatorFromZodMembers recurses), and then use that recursive result
for indexing/rest operations; update the type aliases that reference Members and
ZodValidatorFromConvex (and any uses in VUnion) to use the new recursive utility
so the compiler sees an actual array/tuple type rather than an object.
eed47d3 to
085c812
Compare
ianmacartney
left a comment
There was a problem hiding this comment.
looks like it's only tests right now, but the tests look good, feel free to land once they're passing
Fixes #861
Summary by CodeRabbit
Tests
Improvements