zod icon indicating copy to clipboard operation
zod copied to clipboard

Union behaves differently depending on order

Open numb86 opened this issue 2 years ago • 1 comments

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

numb86 avatar Nov 19 '22 07:11 numb86

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.

VaclavSir avatar Dec 14 '22 10:12 VaclavSir

Is the above answer satisfactory? Or do you have any questions?

I'd like to close this issue if there are no further questions.

JacobWeisenburger avatar Jan 02 '23 22:01 JacobWeisenburger

Thanks! I solved it by writing my own function. Close this issue.

numb86 avatar Jan 03 '23 18:01 numb86