Discriminated union default value on the discriminator
Discriminated union default value on the discriminator
Solution:Jump to solution
```ts
const BaseReservation = z.object({
reservationId: z.number(),
reservedBy: z.string(),
});...
39 Replies
I'd like to set a default value for the discriminator of a discriminated union. is it possible and how?
meaning you want to allow it to be either
undefined
or some literal value coming in, and set it to the literal value by default in the undefined
case?TS Playground - An online editor for exploring TypeScript and JavaS...
The Playground lets you write TypeScript or JavaScript online in a safe and sharable way.
In TS terms i was thinking like:
then when the input object to be parsed is
Zod's output would be
āļø that? yeah, you can do that roughly the same way in Zod:
just be careful about this: the input data is dangerously compatible--without the discriminant, the without room data is assignable to the with room data. Good thing you're parsing it and adding a discriminant š
Nope, I don't think that's it.
My input JSON might not have the haveRoom field at all, in which case Zod should use the default false value for it.
With your schema if I pass as obj to parse:
it throws an invalid discriminator value for haveRoom, it should default to false
oh, right, sorry I forgot about that part, but it's the same as the suggestion from earlier. lemme edit.
Nope, same error as before: Invalid discriminator value. Expected true | false
ah, yeah, this seems like a bug. You can parse either schema just fine, but
discriminatedUnion
complains.
(you can use union
instead, which seems to work fine)
yeah, looking at the implementation, we do not actually run the schemas so we don't get the default
transform, we just look up the input data at that key, and for this case, it's undefined.
Unfortunately (or fortunately depending on the way you look at it), discriminatedUnion
is being deprecated in favor of just a smarter union
, so I doubt Colin will want to spend much effort fixing this.
There's a (very) hacky fix that involves parsing with a union and then piping that to the discriminated union which gives you the "best" of both worlds, but mitigates the poor error reporting performance of union
:
š
This is worse performance-wise but better for error reporting, so I wouldn't do this for like an unbounded array of these objects (in that case, I might consider a custom transform)
oh also, drop the z.never()
that was unnecessary and actually doesn't work because undefined
is not never
š
thanks for all the info, I might run with the "hacky" solution until v4 comes out š
If i was to only use union like you suggested here, how would i do it?
just tried, this still doesn't work š¢
I expected this to work, but it doesn't:
Yeah, that's not going to work because the no room case matches both
Solution
Note that the order here is very important because the without room case matches either, but it'll return the first one that matches, so if you have withoutroom first, even the withroom data will match.
that's it! Thank you very much! You've helped me immensely
This will work nice until v4 comes out š
Amazing. If you want the better error reporting just pipe that into a redundant discriminated union again š