Search code examples
reactjsreact-hook-formzod

How omit certain value from nested zod scheme?


I have the following zod schema, and in some cases there is a field I would like to omit from the schema entirely. I can't just make it optional. I suspect there is some way do it with zod directly. Is there a way to omit fields or to preprocess the schema in some way?

For example, how I can use this schema without this nested field.

const schema = z.object({
  name: z.number(),
  age: z.number(),
  data: z.array(
    z.object({
      id: z.string().optional(),
      name: z.string().nonempty().optional(),
    })
  )
});

const test = schema.shape.data //. ??? how can I omit the name field? 
type typeTest = z.infer<typeof test>; // just data without name field

How I can omit this nested value?


Solution

  • The minimum change to make that would work is:

    const test = schema.shape.data.element.omit({ name: true }).array();
    

    but another option would be to reorganize your schema into a few named parts and use merge to combine them like:

    import { z } from 'zod';
    
    const dataSchema = z.object({
      id: z.string().optional(),
      someOtherField: z.number(),
    });
    
    const namedSchema = z.object({
      name: z.string().nonempty().optional(),
    });
    
    const fullDataSchema = dataSchema.merge(namedSchema);
    
    type Data = z.TypeOf<typeof dataSchema>;
    type FullData = z.TypeOf<typeof fullDataSchema>;
    

    The other option using omit on your base data schema type to get a schema without that field and then use typeof on the resulting schema. If you want to use the schemas in different scenarios I recommend giving them names.

    import { z } from 'zod';
    
    const dataSchema = z.object({
      id: z.string().optional(),
      someOtherField: z.number(),
      name: z.string().nonempty().optional(),
    });
    
    const noNameDataSchema = dataSchema.omit({ name: true });
    
    type Data = z.TypeOf<typeof noNameDataSchema>;
    

    There are pros and cons to either approach but the outcome should be the same. (I personally find myself doing the former more often because I find the code easier to follow)