简体   繁体   中英

How to make an optional property with a default value in Zod

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM