'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 1:[1]

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)

Solution 2:[2]

Correct answer

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.element.omit({ name: true }).array(); 
type typeTest = z.infer<typeof test>; 

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Ksenia