Zod is a powerful TypeScript-first schema validation library that makes it easy to define, validate, and transform data. One of Zod's most powerful features is its ability to work with objects. Zod provides a variety of methods to manipulate and validate object schemas, making it incredibly flexible for handling complex data structures.
In this article, we'll explore the most commonly used Zod object schema methods, complete with examples and practical use cases. By the end, you'll have a solid understanding of how to use Zod effectively to work with objects in your projects.
What Are Zod Schema Objects?
Zod schema objects are used to define and validate the structure of JavaScript objects. They allow you to:
Define the shape of an object: Specify the keys and their corresponding value types.
Manipulate object schemas: Extend, merge, pick, omit, or modify object schemas.
Handle edge cases: Make fields optional, nullable, or provide fallback values.
Validate complex data structures: Work with nested objects, arrays, and more.
Let’s dive into the most important Zod object schema methods and how to use them.
1. Defining Object Schemas
z.object()
The z.object()
method is used to define the shape of an object.
import { z } from 'zod';
const userSchema = z.object({
name: z.string(),
age: z.number(),
email: z.string().email(),
});
userSchema.parse({
name: "John Doe",
age: 30,
email: "john.doe@example.com",
}); // Valid
Use Case: Use z.object()
to define the structure of an object.
2. Accessing Object Properties
.shape
The .shape
property allows you to access the schemas for individual keys in an object.
const userSchema = z.object({
name: z.string(),
age: z.number(),
});
const nameSchema = userSchema.shape.name; // z.string()
const ageSchema = userSchema.shape.age; // z.number()
Use Case: Use .shape
to access or reuse individual schemas within an object.
.keyof()
The .keyof()
method creates a schema that validates the keys of an object.
const userSchema = z.object({
name: z.string(),
age: z.number(),
});
const keySchema = userSchema.keyof(); // z.enum(["name", "age"])
keySchema.parse("name"); // Valid
keySchema.parse("invalidKey"); // Throws ZodError
Use Case: Use .keyof()
to validate that a value is one of the keys in an object.
3. Extending and Merging Objects
.extend()
The .extend()
method allows you to add new fields to an existing object schema.
const baseSchema = z.object({
name: z.string(),
});
const extendedSchema = baseSchema.extend({
age: z.number(),
});
extendedSchema.parse({
name: "John",
age: 30,
}); // Valid
Use Case: Use .extend()
to add additional fields to an object schema.
.merge()
The .merge()
method combines two object schemas into one.
const schemaA = z.object({ name: z.string() });
const schemaB = z.object({ age: z.number() });
const mergedSchema = schemaA.merge(schemaB);
mergedSchema.parse({
name: "John",
age: 30,
}); // Valid
Use Case: Use .merge()
to combine two object schemas into a single schema.
4. Picking and Omitting Fields
.pick()
The .pick()
method creates a new schema with only the specified keys.
const userSchema = z.object({
name: z.string(),
age: z.number(),
email: z.string().email(),
});
const pickedSchema = userSchema.pick({ name: true, email: true });
pickedSchema.parse({
name: "John",
email: "john@example.com",
}); // Valid
Use Case: Use .pick()
to create a subset of an object schema.
.omit()
The .omit()
method creates a new schema without the specified keys.
const userSchema = z.object({
name: z.string(),
age: z.number(),
email: z.string().email(),
});
const omittedSchema = userSchema.omit({ age: true });
omittedSchema.parse({
name: "John",
email: "john@example.com",
}); // Valid
Use Case: Use .omit()
to exclude specific keys from an object schema.
5. Making Fields Optional or Required
.partial()
The .partial()
method makes all fields in an object optional.
const userSchema = z.object({
name: z.string(),
age: z.number(),
});
const partialSchema = userSchema.partial();
partialSchema.parse({}); // Valid
partialSchema.parse({ name: "John" }); // Valid
Use Case: Use .partial()
when you want to make all fields in an object optional.
.deepPartial()
The .deepPartial()
method makes all fields, including nested objects, optional.
const userSchema = z.object({
name: z.string(),
address: z.object({
city: z.string(),
zipCode: z.string(),
}),
});
const deepPartialSchema = userSchema.deepPartial();
deepPartialSchema.parse({}); // Valid
deepPartialSchema.parse({ address: {} }); // Valid
Use Case: Use .deepPartial()
when you want to make all fields, including nested objects, optional.
.required()
The .required()
method makes all optional fields required.
const userSchema = z.object({
name: z.string().optional(),
age: z.number().optional(),
});
const requiredSchema = userSchema.required();
requiredSchema.parse({ name: "John", age: 30 }); // Valid
requiredSchema.parse({ name: "John" }); // Throws ZodError
Use Case: Use .required()
to enforce that all optional fields are present.
6. Advanced Object Schema Methods
.passthrough()
The .passthrough()
method allows unknown keys to pass through the schema without validation.
const userSchema = z.object({
name: z.string(),
}).passthrough();
userSchema.parse({
name: "John",
age: 30, // Unknown key, but allowed
}); // Valid
Use Case: Use .passthrough()
when you want to allow additional keys in the object.
.strict()
The .strict()
method ensures that no unknown keys are present in the object.
const userSchema = z.object({
name: z.string(),
}).strict();
userSchema.parse({
name: "John",
age: 30, // Unknown key, throws ZodError
}); // Throws ZodError
Use Case: Use .strict()
to enforce that no extra keys are present in the object.
.strip()
The .strip()
method removes unknown keys from the object.
const userSchema = z.object({
name: z.string(),
}).strip();
const result = userSchema.parse({
name: "John",
age: 30, // Unknown key, removed
});
console.log(result); // { name: "John" }
Use Case: Use .strip()
to clean up objects by removing unknown keys.
.catchall()
The .catchall()
method defines a schema for any unknown keys in the object.
const userSchema = z.object({
name: z.string(),
}).catchall(z.number());
userSchema.parse({
name: "John",
age: 30, // Unknown key, validated as number
}); // Valid
Use Case: Use .catchall()
to validate unknown keys in an object.
Conclusion
Zod's object schema methods provide a powerful and flexible way to define, validate, and manipulate object structures. Whether you're working with simple or complex data, Zod has the tools you need to ensure your data is valid and type-safe.
By mastering these methods, you can build robust applications with confidence. For more advanced use cases, check out the official Zod documentation.
Happy coding! 🚀