Given the following snippet :
const person = object({
name: string().or(() => 'john'),
age: number(),
});
type Person = Infer<typeof person>;
Here Person
is :
type Person = {
name: string;
age: number;
}
This is a correctly inferred type but it's an output type, because it's the type of the object returned by the person
function.
Let's say we have a method that post a user to an API that expect a Person
object :
function createPerson(input: unknown) {
const newPerson = person(input);
axios.post('/api/person', newPerson); // send a Person object
}
It's weird to see unknown
as input in a TypeScript project, here we could write code like createPerson(12)
and TS would not complain.
Here we cannot type the input
parameter via input: Person
because the name property is not optional.
But name
should be optional because it has a default value.
Here we see that the same schema has a different input and an output type.
What it can take as input is not the same as what it actually return.
We could imagine a InferInput
type that would return the input type of a schema.
type PersonInput = InferInput<typeof person>;
function createPerson(input: PersonInput) {
const newPerson = person(input);
axios.post('/api/person', newPerson); // send a Person object
}
Now we have a proper type for the input
parameter.
This feature has been implemented in Zod :
const stringToNumber = z.string().transform((val) => val.length);
type input = z.input<typeof stringToNumber>; // string
type output = z.output<typeof stringToNumber>; // number