zod
zod copied to clipboard
Union behaves differently depending on order
Used v3.19.1
.
Union
seems to behave differently depending on the order.
const Foo = z
.object({
a: z.number(),
b: z.number(),
})
.partial();
const Bar = z
.object({
x: z.number(),
y: z.number(),
})
.partial();
// the order of Foo and Bar is reversed
const Baz = z.union([Foo, Bar]);
const Qux = z.union([Bar, Foo]);
const onlyA = { a: 1 };
const onlyX = { x: 8 };
const all = { a: 1, b: 2, x: 8, y: 9 };
console.log(Baz.parse(onlyA)); // { a: 1 }
console.log(Qux.parse(onlyA)); // {}
console.log(Baz.parse(onlyX)); // {}
console.log(Qux.parse(onlyX)); // { x: 8 }
console.log(Baz.parse(all)); // { a: 1, b: 2 }
console.log(Qux.parse(all)); // { x: 8, y: 9 }
Is this expected behavior? If so, I would appreciate it if you could tell me what I should do to achieve what I want to do.
I want to express the following
Object with optional properties a
and b
or
Object with optional properties x
and y
So I would expect a result like below.
ExpectedSchema.parse({ a: 1, b: 2 }) // { a: 1, b: 2 }
ExpectedSchema.parse({ a: 1 }) // { a: 1 }
ExpectedSchema.parse({ x: 8, y: 9 }) // { x: 8, y: 9 }
ExpectedSchema.parse({ x: 8 }) // { x: 8 }
ExpectedSchema.parse({ c: 3 }) // {}
ExpectedSchema.parse({ a: 1, x: 8 }) // Error
ExpectedSchema.parse({ a: 1, b: 2, x: 8 }) // Error
Hi, I just ran into a similar issue.
The thing is that z.objects
is non-strict by default, meaning that it strips unknown properties. In other words, if you parse all
with either Foo
or Bar
, it will succeed:
Foo.parse(all) // { a: 1, b: 2 }
Bar.parse(all) // { x: 8, y: 9 }
If you want it to fail on all
, then you have to use .strict()
on the object schema definition.
Is the above answer satisfactory? Or do you have any questions?
I'd like to close this issue if there are no further questions.
Thanks! I solved it by writing my own function. Close this issue.