I have a function that randomly returns one of these objects:
{ name: "Tommy", age: 15 }
{ car: "BMW" }
Let's say I want to run this function and hope that it returns me the User object instead of the Car. To verify this I want to pass it Zod schema as an argument so the function will parse it and throw an error if the random object doesn't match my schema.
Otherwise, if the random object matches schema, I want to get this object returned from the function with the inferred type so I know that i have name
and age
properties.
That's my code:
import { z } from "zod";
const User = z.object({
name: z.string(),
age: z.number()
});
const randomObjects = [
{
name: "Tommy",
age: 16
},
{
car: "BMW"
}
];
export const getRandomObject = (
Schema: z.AnyZodObject
): z.infer<typeof Schema> => {
try {
const obj = Math.random() > 0.5 ? randomObjects[0] : randomObjects[1];
Schema.parse(obj);
return obj;
} catch (error) {
throw new Error("Sorry, wrong Schema passed");
}
};
const user = getRandomObject(User);
console.log(user);
user
is being inferred as { [x: string]: any; }
.
How to make typescript know that it is an User object with name
and age
properties?
Codesandbox: https://codesandbox.io/s/zod-v3g3hp?file=/src/index.ts:513-735
CodePudding user response:
You should be using a generic parameter so that TS can infer the schema type and reuse it:
export const getRandomObject = <S extends z.AnyZodObject>(
Schema: S
): z.infer<S> => {
CodePudding user response:
To infer the type of the returned object as User, you can use the infer type utility provided by zod and pass it the User schema as a type parameter.
Here is an example of how you can modify your code to correctly infer the type of the returned object:
import { z } from "zod";
const User = z.object({
name: z.string(),
age: z.number()
});
const randomObjects = [
{
name: "Tommy",
age: 16
},
{
car: "BMW"
}
];
export const getRandomObject = (
Schema: z.AnyZodObject
): z.infer<typeof Schema> => {
try {
const obj = Math.random() > 0.5 ? randomObjects[0] : randomObjects[1];
Schema.parse(obj);
return obj;
} catch (error) {
throw new Error("Sorry, wrong Schema passed");
}
};
const user = getRandomObject(User);
console.log(user);
With this change, the type of the user variable will be inferred as User, so you will have access to the name and age properties of the returned object.