Objects
Zod provides powerful object validation capabilities.
Basic Usage
ts
import { z } from "zod";
const User = z.object({
username: z.string(),
age: z.number(),
email: z.string().email(),
isAdmin: z.boolean().optional(),
});
type User = z.infer<typeof User>;
// { username: string; age: number; email: string; isAdmin?: boolean }
Accessing Object Properties
Use .shape
to access the schema of object properties:
ts
const User = z.object({
username: z.string(),
age: z.number(),
});
User.shape.username; // returns string schema
User.shape.age; // returns number schema
Extending Objects
Use .extend
to add new properties:
ts
const User = z.object({
username: z.string(),
});
const AdminUser = User.extend({
isAdmin: z.boolean(),
permissions: z.array(z.string()),
});
Merging Objects
Use .merge
to combine two object schemas:
ts
const BaseUser = z.object({
id: z.string(),
username: z.string(),
});
const UserDetails = z.object({
age: z.number(),
email: z.string().email(),
});
const FullUser = BaseUser.merge(UserDetails);
// equivalent to:
// z.object({
// id: z.string(),
// username: z.string(),
// age: z.number(),
// email: z.string().email(),
// })
Picking and Omitting
Use .pick
and .omit
to select or ignore specific properties:
ts
const User = z.object({
id: z.string(),
username: z.string(),
age: z.number(),
email: z.string(),
});
// Pick only certain fields
const UserBasics = User.pick({ username: true, age: true });
// { username: string; age: number }
// Omit certain fields
const UserWithoutId = User.omit({ id: true });
// { username: string; age: number; email: string }
Optional Fields
Use .partial
to make all fields optional:
ts
const User = z.object({
username: z.string(),
age: z.number(),
});
const PartialUser = User.partial();
// { username?: string; age?: number }
// Deep partial
const DeepPartialUser = User.deepPartial();
Strict Mode
By default, Zod strips out unrecognized keys. Use .strict()
to forbid extra fields:
ts
const User = z.object({
username: z.string(),
}).strict();
User.parse({
username: "bob",
extra: "field", // will throw error
});
// Or use .passthrough() to keep extra fields
const FlexibleUser = z.object({
username: z.string(),
}).passthrough();
FlexibleUser.parse({
username: "bob",
extra: "field", // will be kept
});
Catchall Properties
Use .catchall
to define the type of unknown keys:
ts
const NumberCache = z.object({
id: z.string(),
}).catchall(z.number());
// equivalent to { [k: string]: number } & { id: string }
NumberCache.parse({
id: "xyz123",
count: 42,
amount: 123,
}); // passes