How to properly set up a discriminated union?
I have put together the following...
export const UnionTypeOne = type({
type: '"1"',
foo: 'string',
})
export const UnionTypeTwo = type({
type: '"2"',
bar: 'number',
})
export const UnionTypeThree = type({
type: '"3"',
baz: 'boolean',
})
export const ResponseSchema = type({
union: UnionTypeOne.or(UnionTypeTwo).or(UnionTypeThree),
})
The thing I'm missing here is that my union key is not properly type checked where I want to essentially set up a union where any of the values in the union have to have a specifier, in this case type. Maybe I'm just missing it in the docs, but I can't figure out how to set this up.
Hi @Scalahansolo, I believe the key to discriminated unions is to include the other keys as optional & never, e.g.:
const foo = type({
type: "'1'",
foo: "string",
"bar?": "never",
"baz?": "never"
});
const bar = type({
type: "'2'",
bar: "number",
"foo?": "never",
"baz?": "never"
});
const baz = type({
type: "'3'",
baz: "boolean",
"foo?": "never",
"bar?": "never"
});
const union = foo.or(bar).or(baz);
Give something like this a try and let me know how it goes!
That isn't what a discriminated union is. Both Zod and Valibot support these like so.
Valibot
// Discriminated union components
export const UnionTypeOne = v.object({
type: v.literal('1'),
foo: v.string(),
})
export const UnionTypeTwo = v.object({
type: v.literal('2'),
bar: v.number(),
})
export const UnionTypeThree = v.object({
type: v.literal('3'),
baz: v.boolean(),
})
export const ResponseSchema = v.object({
union: v.variant('type', [UnionTypeOne, UnionTypeTwo, UnionTypeThree]),
})
Zod
export const UnionType = z.enum(['1', '2', '3'])
export const UnionTypeOne = z.object({
type: UnionType.enum['1'],
foo: z.string(),
})
export const UnionTypeTwo = z.object({
type: UnionType.enum['2'],
bar: z.number(),
})
export const UnionTypeThree = z.object({
type: UnionType.enum['3'],
baz: z.boolean(),
})
export const ResponseSchema = z.object({
union: z.discriminatedUnion('type', [
UnionTypeOne,
UnionTypeTwo,
UnionTypeThree,
]),
})
In both of these cases, when establishing the key union, there is type checking happening to ensure that each schema being added to the union has the type key.