zod icon indicating copy to clipboard operation
zod copied to clipboard

Intersection between `z.object` and `z.record` incorrectly merges validators

Open lars-berger opened this issue 2 years ago • 3 comments

When intersecting a z.object and a z.record, zod applies validators for the keys and values of the record to the rest of the object.

const ConfigSchema = z
  .object({
    name: z.object({
      first: z.string(),
    }),
  })
  .and(
    z.record(
      z.enum(['a', 'b']),
      z.object({
        sub: z.string(),
      })
    )
  );

const validInput: z.infer<typeof ConfigSchema> = { // typescript type is correct and doesn't complain here 👍
  name: {
    first: '',
  },
  a: {
    sub: '',
  },
};

ConfigSchema.parse(validInput);
// ^ this throws 2 errors because:
// 1. 'name' doesn't match ['a', 'b']
// 2. 'name.sub' is required (even though this will never exist)
image

Reproduction URL: stackblitz.com

Expected behavior: validators for record keys and values should only apply to the record.

The same problem occurs with intersections of records that have native enum keys and template literal keys (eg. [key: dynamic/${string}]).

lars-berger avatar Jul 12 '23 09:07 lars-berger

Related to #2195

GauBen avatar Dec 08 '23 10:12 GauBen

is there any alternative?

yovanoc avatar Jan 27 '24 13:01 yovanoc