Search code examples
typescripttypestype-conversionzod

Property "shape" not accessible when using generics with toZod


TL;DR I have a type error here is the TS PLAYGROUND

I want to have type safety when creating my zod schemas. To do so, I use the type of my data, like this one:

type Option = { id: number };

With this type, I know the exact keys that my zod object schema should have and I use toZod to transform the type number into a z.number() type.

For example, here is a function to create an option schema (ts playground):

type Option = { id: number };

function createOptionSchema(input: {
  [K in keyof Option]: toZod<Option>["shape"][K];
}) {
  const OptionSchema: toZod<Option> = z.object(input);

  return OptionSchema;
}
  • these are valid :
const test1 = createOptionSchema({id: z.number()})
const test2 = createOptionSchema({id: z.number().int()})
  • these throw a type error as expected :
const test3 = createOptionSchema({id: z.string()})
const test4 = createOptionSchema({name: z.number()})
const test5 = createOptionSchema({id: z.number().optional()})

Currently, this function only works for the Option type, I would like to use the same function for all my data types. So I did that:


function createSchema<T extends Record<string, unknown>>(input: {
  [K in keyof T]: toZod<T>["shape"][K];
}) {
  const Schema: toZod<T> = z.object(input);

  return Schema;
}

Now I get this error:

Type '"shape"' cannot be used to index type 'toZod<T>'

I could not find any solution so far, any idea?

Useful links:

I tried to replace the toZod type for a custom one but could not manage to transform types into zod schema types.

I tried to use satisfies as well, without success.


Solution

  • Thank you to Matt Pocock for this one.

    
        function createSchema<
          T extends Record<string, any>,
        >(input: {
          [K in keyof T]: z.Schema<T[K]>;
        }) {
          const Schema = z.object(input);
        
          return Schema;
        }