0

I've been learning Typescript for a few months and i started to discover zod recently, and i wonder how to build such a util getter such as z.infer<>, z.input<> or even z.output<>

What i understand is that z is a class that has a getter "method" that takes a generic and it returns a type, but i have no idea of how this works

I tried to replicate it but couldn't figure it out, can someone help?

sqmasep
  • 11
  • 2
  • I had to do this for my [project](https://github.com/kelsny/synth), and essentially, the classes already hold the type you want - the getter type is just to make it easier to retrieve. – kelsny Nov 01 '22 at 22:35

2 Answers2

1

If we have some class that has a generic type and uses it:

class Validator<T> { validate(value: any): value is T { /* implementation does not matter */ return true; } }

Then we can extract that generic type with infer:

type Infer<V> = V extends Validator<infer T> ? T : never;

You'll be able to use it like this:

const validator = new Validator<string>();

type S = Infer<typeof validator>; // string

This is the basis of Zod's z.Infer.

Playground

kelsny
  • 23,009
  • 3
  • 19
  • 48
0

From my quick digging of the source code, these types seem to be defined in helpers/types.ts:

export type TypeOf<T extends ZodType<any, any, any>> = T["_output"];
export type input<T extends ZodType<any, any, any>> = T["_input"];
export type output<T extends ZodType<any, any, any>> = T["_output"];
export type { TypeOf as infer };
// ...
export abstract class ZodType<
  Output = any,
  Def extends ZodTypeDef = ZodTypeDef,
  Input = Output
> {
  readonly _type!: Output;
  readonly _output!: Output;
  readonly _input!: Input;
  readonly _def!: Def;
// ...

That's how you can build them.

rainbow.gekota
  • 1,075
  • 2
  • 6
  • 18