Reputation: 7061
I'm using Zod and I want to define one schema for user input that has an optional field with a default value. However, it is being impossible for me to make the runtime behaviour match the inferred type. What I want, is the field to be optional, and when not provided, or provided as undefined, use the default value. If I want this behaviour I can't have the field optional in the generated type, and if I manage to make it optional in the generated type, then it will not get a default value during runtime.
Let me explain it with code:
import { Timestamp } from 'firebase/firestore';
import { z } from 'zod';
export const someSchema = z.object({
id: z.string(),
timestamp: z.instanceof(Timestamp),
type: z.enum(['fever', 'constipation']),
notes: z.string().optional().default(''),
});
export const someInput = someSchema
.omit({ id: true })
.merge(
z.object({
timestamp: z
.date()
.optional()
.default(() => new Date()),
}),
)
.partial({
notes: true,
});
export const schemaArray = z.array(someSchema);
export type Schema = z.infer<typeof someSchema>;
export type SchemaInput = z.infer<typeof someInput>; // <- Here I expect timestamp to be optional, but it is required
function a({ type, timestamp, notes}: SchemaInput){
someInput.parse({
type, timestamp, notes
})
}
a({type: 'fever'}) <- Error, timestamp is required
Upvotes: 15
Views: 28321
Reputation: 7061
As I was pointed out on github schemas usually have an input and an output type. By default, what z.infer
does is returning the output type, which is probably the most common usage scenario. Thankfully there is also a method to extract the expected input for the parser, and that is exactly what I needed:
export type SchemaInput = z.input<typeof someInput>;
function a({ type, timestamp, notes}: SchemaInput){
someInput.parse({
type, timestamp, notes
})
Now the inferred schema looks like this:
type SchemaInput = {
timestamp?: Date | undefined;
notes?: string | undefined;
type: "fever" | "constipation";
}
Which is exactly what I needed for a function that takes this input and uses the validator to ensure it has the proper format.
Upvotes: 16