Let’s say I have the following example schema:
const Z_GlobalSettings = z.object({
crust: z.enum(["thin", "thick"]).default("thin"),
toppings: z.array(z.string()).min(1).max(5).default(["cheese"]),
sauce: z.enum(["marinara", "bbq", "ranch"]).default("marinara"),
delivery_time: z.string().optional(),
order_notes: z.string().max(50).optional(),
contact_email: z.string().email().optional(),
setting_1: z.boolean(),
setting_2: z.boolean().optional(),
});
type GlobalSettings = z.infer<typeof Z_GlobalSettings>;
How can I programmatically extract the types that contain booleans, or whichever arbitrary type I’m looking for? For example, if I want the booleans from the schema, I’d want my new schema to look like:
const Z_OnlyBoolean = z.object({
setting_1: z.boolean(),
setting_2: z.boolean().optional(),
});
I was initially able to accomplish this using Typescript:
type BooleanSettings = {
[K in keyof GlobalSettings as GlobalSettings[K] extends boolean | undefined
? K
: never]?: boolean;
};
However, this wasn’t working when I wanted to differentiate between z.string()
and z.enum(["example1", "example2"])
, since they’d both come through as strings. This is why I’m hoping to find a way to filter a schema by type since Zod is keeping track of the difference between strings and enums, but the only way I can find in the documentation is to use the .pick()
method and choose them one-by-one. This won’t be great if I add properties in the future, since I’ll need to update the filtered schema as well, and won’t be great for usability since I’ll need to make a new schema for every type I want to extract.
Any ideas on how to accomplish this?