Search code examples
typescriptzod

Zod record with required keys


I'm trying to create a dictionary like zod schema for an object that has many keys, defined elsewhere, and they all have the same value type. And all keys are required.

const KeysSchema = z.enum(['a', 'b', 'c', /*...*/]) // long key list
const ObjSchema = z.record(KeysSchema, z.number())

But the yielded type is:

{
    a?: number | undefined;
    b?: number | undefined;
    c?: number | undefined;
}

But what I want is:

{
    a: number;
    b: number;
    c: number;
}

I want: Record<'a', 'b', 'c', number>

but it's giving me: Partial<Record<"a" | "b" | "c", number>>

And I can't call z.record(...).required() because that's not a thing for zod records.

How can I make a record type with required keys?

See Typescript playground


Solution

  • Managed to solve it with a .refine()

      .refine((obj): obj is Required<typeof obj> =>
        KeysSchema.options.every((key) => obj[key] != null),
      )
    

    It checks every key in the KeysSchema and asserts that all keys are present, and it's not a partial at all.

    See Playground