multiply a variant's flattened choice into one closed object per combination, where the refusal stood - #230
Merged
Merged
Conversation
…ination, where the refusal stood A struct variant flattening a multi-branch source, or an Option-wrapped one, was refused: the variant's members are written inside the union member that carries them, and a single closed object cannot describe a member with more than one key set. The other two surfaces never had the problem — TypeScript distributes an intersection over a union, and the JSON document multiplies at run time — so the refusal was a Zod limitation blamed on the variant. Zod gets the multiplication now, written out at expansion: one closed object per combination of the variant's own members with each key set its sources can write, joined in a union. An Option-wrapped source contributes its keys and their absence; a multi-branch source one combination per branch; several sources multiply; a single-branch source collapses to the one object it always was, byte-identical. The variant still contributes exactly one member to its enclosing union, so nothing about how the four tagged forms assemble moves — the internally tagged form drops to a plain union exactly as it already does for any flattening variant. The three runtime behaviours the design leans on were measured against zod 4.4.3 before anything was built, not assumed: a union nested in a union accepts each inner branch and rejects the mixed and partial shapes; a discriminated union still discriminates when a member's content is itself a union, failing an unknown discriminator with the single issue at the tag's path; and two separately written closed objects validate identically. The final schemas were then re-emitted and run against real serde payloads: every branch of every multiplied variant accepted, every stale, mixed and unknown-key shape rejected. What stays refused is the different question it always was: a flattened plain enum, and a union with a non-object member — sources with no members to merge. The two refusals this replaces come off with their tests turned into acceptance; every other flatten fixture is pinned byte-identical. just check, just quick, just lint-all across all 68 toggles, and the test powerset across all 68 in four partitions — all green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A struct variant flattening a multi-branch source, or an Option-wrapped one,
was refused: the variant's members are written inside the union member that
carries them, and a single closed object cannot describe a member with more
than one key set. The other two surfaces never had the problem — TypeScript
distributes an intersection over a union, and the JSON document multiplies at
run time — so the refusal was a Zod limitation blamed on the variant.
Zod gets the multiplication now, written out at expansion: one closed object
per combination of the variant's own members with each key set its sources can
write, joined in a union. An Option-wrapped source contributes its keys and
their absence; a multi-branch source one combination per branch; several
sources multiply; a single-branch source collapses to the one object it always
was, byte-identical. The variant still contributes exactly one member to its
enclosing union, so nothing about how the four tagged forms assemble moves —
the internally tagged form drops to a plain union exactly as it already does
for any flattening variant.
The three runtime behaviours the design leans on were measured against zod
4.4.3 before anything was built, not assumed: a union nested in a union accepts
each inner branch and rejects the mixed and partial shapes; a discriminated
union still discriminates when a member's content is itself a union, failing an
unknown discriminator with the single issue at the tag's path; and two
separately written closed objects validate identically. The final schemas were
then re-emitted and run against real serde payloads: every branch of every
multiplied variant accepted, every stale, mixed and unknown-key shape rejected.
What stays refused is the different question it always was: a flattened plain
enum, and a union with a non-object member — sources with no members to merge.
The two refusals this replaces come off with their tests turned into
acceptance; every other flatten fixture is pinned byte-identical.
just check, just quick, just lint-all across all 68 toggles, and the test
powerset across all 68 in four partitions — all green.