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?
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)