0

I want to force a Zod type based on a TypeScript interface:

import { z } from 'zod';

interface Foo {
  id: string;
  count: number;
}

                  //
const t = z.object<Foo>({
  count: z.number(),
  id: z.string()
})

How can I do it? The code above doesn't work.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Bazinga
  • 10,716
  • 6
  • 38
  • 63

1 Answers1

3

You can give t the respective z.ZodType type.

const t: z.ZodType<Foo> = z.object({
  count: z.number(),
})
// Error: Property 'id' is missing in type '{ count: number; }' but required in type 'Foo'

Alternatively, you can use a helper function:

const schemaForType = <T>() => <S extends z.ZodType<T, any, any>>(arg: S) => {
  return arg;
};

schemaForType<Foo>()(
  z.object({
    id: z.string(),
    count: z.number(),
  })
);

schemaForType<Foo>()(
  z.object({
    id: z.string(),
  })
// ^^^^^^^^^^^^^^^ Error:  Property 'count' is missing in type '{ id: string; }' but required in type 'Foo'.(2345)
);

Playground

Tobias S.
  • 21,159
  • 4
  • 27
  • 45
  • Thanks. Is there any way to not create a variable only for that? – Bazinga Nov 15 '22 at 12:08
  • you could also use a helper-function. See my edit – Tobias S. Nov 15 '22 at 12:21
  • That's great. Any reason I don't get autocomplete from typescript when trying to see the missing properties? – Bazinga Nov 15 '22 at 12:27
  • Seems like there are too many layers of indirection which makes the autocompletion not realize what properties are supposed to be in the object. But hard to properly judge this without looking into the compiler :/ – Tobias S. Nov 15 '22 at 12:33