- Published on
How to Merge Multiple Zod Object Schemas: A Complete Guide
- Authors
- Name
- Ripal & Zalak
How to Merge Multiple Zod Object Schemas: A Complete Guide
Merging multiple Zod object schemas can be essential for building complex validation rules in your TypeScript applications. Whether you’re working with form validations, APIs, or custom logic, Zod provides powerful utilities for combining schemas effectively.
In this guide, we’ll explore several methods to merge Zod schemas, focusing on practical examples and best practices.
The Problem
You have three schemas for different types of blog posts:
- Image Post: Requires an image attachment and optional text.
- Video Post: Requires a video attachment and optional text.
- Text Post: Requires text only, with no attachments.
Here are the schemas:
import { z } from 'zod'
const imagePostSchema = z.object({
body: z.string().max(500).optional().or(z.literal('')),
attachmentType: z.literal('img'),
attachment: z.string().url(), // Assume URL for simplicity
})
const videoPostSchema = z.object({
body: z.string().max(500).optional().or(z.literal('')),
attachmentType: z.literal('video'),
attachment: z.string().url(), // Assume URL for simplicity
})
const textPostSchema = z.object({
body: z.string().max(500),
attachmentType: z.null(),
attachment: z.null(),
})
Now, the goal is to merge these schemas into a single schema to allow users to submit any type of post.
z.union
for Unions
Solution 1: Use The simplest way to merge schemas is by creating a union using z.union
. This approach validates objects that match any one of the provided schemas.
Implementation:
const postSchema = z.union([imagePostSchema, videoPostSchema, textPostSchema])
Usage:
const result = postSchema.safeParse({
body: 'Check out this image!',
attachmentType: 'img',
attachment: 'https://example.com/image.jpg',
})
console.log(result.success) // true if valid
z.discriminatedUnion
for Discriminated Unions
Solution 2: Use If the schemas can be distinguished by a common field, such as attachmentType
, you can use z.discriminatedUnion
for better performance and type inference.
Implementation:
const postSchema = z.discriminatedUnion('attachmentType', [
imagePostSchema,
videoPostSchema,
textPostSchema,
])
z.discriminatedUnion
?
Why Use - Performance: It only checks the schema corresponding to the
attachmentType
value. - Type Inference: TypeScript infers the correct type based on the discriminant.
Usage:
const result = postSchema.safeParse({
body: 'Watch this video!',
attachmentType: 'video',
attachment: 'https://example.com/video.mp4',
})
if (result.success) {
console.log(result.data.attachmentType) // "video"
}
z.object
Spreading
Solution 3: Combine Schemas with If you want to merge all schemas into a single comprehensive schema, you can use the shape
property to spread their fields.
Implementation:
const combinedSchema = z.object({
...imagePostSchema.shape,
...videoPostSchema.shape,
...textPostSchema.shape,
})
Use Case:
This approach is useful when the fields from all schemas need to coexist in one schema.
Drawback:
This doesn’t enforce mutual exclusivity between schema types. Use unions or discriminated unions for stricter validation.
z.intersection
for Common Validations
Solution 4: Use If you need to combine schemas with overlapping validations, use z.intersection
.
Implementation:
const sharedSchema = z.intersection(imagePostSchema, videoPostSchema)
Drawback:
This method works for AND
logic (objects must satisfy both schemas) and is not suitable for mutually exclusive schemas like in this use case.
Best Practices
- Prefer
z.discriminatedUnion
: When a common field distinguishes schemas, it’s the most efficient and type-safe method. - Avoid
z.intersection
for Unions: Use it only for overlapping fields withAND
logic. - Validate Early: Use
safeParse
orparse
at data entry points to catch errors early. - Leverage TypeScript: Type inference from Zod improves code reliability and developer experience.
Conclusion
Merging multiple Zod schemas depends on your specific requirements:
- Use
z.union
for basic combinations. - Use
z.discriminatedUnion
for efficient validation with a shared field. - Use schema spreading for comprehensive schema creation.
By following these approaches, you can build robust and flexible validation logic for your applications.
Key Takeaways
z.union
: Simple merging of schemas.z.discriminatedUnion
: Efficient validation with type inference.- Schema Spreading: Combine fields into one schema.
z.intersection
: Combine schemas with overlapping validations.
With these techniques, you can manage complex validation scenarios effectively using Zod in TypeScript.