feature request: combining/nesting/extending discriminated unions
See original GitHub issueIn our app we have some data coming from an external service that’s modelled as a combination of 2 discriminated unions, e.g.
[
{ type: "quote", attribution: "..." },
{ type: "textAndMedia", mediaType: "image", image: {...} }
{ type: "textAndMedia", mediaType: "video", video: {...} }
]
But attempting to model it with zod fails with the error:
The discriminator value could not be extracted from all the provided schemas
const t = z.discriminatedUnion("type", [
z.object({ type: z.literal("one"), foo: z.string() }),
z.object({ type: z.literal("two"), bar: z.string() }),
z.discriminatedUnion("secondType", [
{ type: z.literal("three"), secondType: z.literal("a") },
]),
]);
An extra problem we’ve ran into is the nested discriminator is defined elsewhere, but unlike objects it doesn’t have a .extend
method, and a ZodDiscriminatedUnion
isn’t a valid arg for ZodObject.merge
const otherDiscriminator = z.discriminatedUnion("secondType", [
z.object({ secondType: z.literal("a") }),
z.object({ secondType: z.literal("b") }),
]);
z.discriminatedUnion("type", [
z.object({ type: z.literal("one"), foo: z.string() }),
z.object({ type: z.literal("two"), bar: z.string() }),
otherDiscriminator.extend({ type: z.literal("three") }),
]);
Instead of extending I considered extracting the discriminator options and mapping over them, but zod can't infer that correctly. Code sample in toggle
const otherDiscriminatorOptions = [
z.object({ secondType: z.literal("a") }),
z.object({ secondType: z.literal("b") }),
] as const;
const otherDiscriminator = z.discriminatedUnion("secondType", [
...otherDiscriminatorOptions,
]);
z.discriminatedUnion("type", [
z.object({ type: z.literal("one"), foo: z.string() }),
z.object({ type: z.literal("two"), bar: z.string() }),
z.discriminatedUnion("secondType", [
...otherDiscriminatorOptions.map((option) => ({
type: z.literal("three"),
...option,
})),
]),
]);
Issue Analytics
- State:
- Created a year ago
- Reactions:2
- Comments:8 (1 by maintainers)
Top Results From Across the Web
Proposal: Add Discriminated Unions using a new Type #14208
Although c# 7 contains various features for pattern matching, ... a proposal for adding Discriminated Union types, with exhaustive matching.
Read more >Discriminated Unions and Exhaustiveness Checking in ...
In this article, you'll find an example of what we learned about discriminated unions and exhaustiveness checking in Typescript and why it's ...
Read more >Demystifying TypeScript Discriminated Unions - CSS-Tricks
TypeScript discriminated unions are types where a key or value can be used to differentiate between the keys and values of several types...
Read more >Discriminated Unions - F# | Microsoft Learn
Discriminated unions provide support for values that can be one of a number of named cases, possibly each with different values and types....
Read more >type safety - Discriminated union in C# - Stack Overflow
I like the direction of the accepted solution but it doesn't scale well for unions of more than three items (e.g. a union...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Wanted to bump as having the ability to use a discriminated union with
extend/merge
would be really, really nice!@maxArturo nice!
I can confirm that your changes to allow using a
ZodDiscriminatedUnion
as an element of other discriminated unions fixes the issue. Requiring the discriminated unions to share the same discrimination key seems reasonable to me.In our specific case all of the unions we are discriminating, and occasionally nesting, have the same exact discrimination key. Also, the key is valued uniquely across all objects.