Table of contents
Introduction
This post explores Zod, a library that provides "TypeScript-first schema validation with static type inference". We'll explore how it works and why it's so useful.
Manual Validation
If you've found yourself manually writing validation checks it can get tedious pretty quickly. For example, you might need to write checks to make sure that required fields are provided and data is in the correct format and/or fits certain parameters like a number being within a certain range.
if (name === '') {
errors.push('Name is required')
}
if (name.length < 3) {
errors.push('Name must be at least 3 characters')
}
if (name.length > 30) {
errors.push('Name must be 30 or fewer characters long')
}
Schema Validation
This is where Zod comes in really handy. Here's an example of how we can define a userSchema
where name, age, email are all required with their expected types and a min/max length for the name. To make it optional you will need to add .optional()
.
import { z } from 'zod';
// Define the schema with validation rules
const userSchema = z.object({
name: z.string().min(3).max(30),
age: z.number(),
email: z.string().email()
});
// Infer TypeScript type from the schema
type User = z.infer<typeof userSchema>;
// Parse data using the schema and handle the result
const result = userSchema.safeParse({ name, age, email })
if (result.success) {
// Everything looks good and valid
} else {
// Invalid... handle using result.error
}
Using z.infer
you can infer the TypeScript type from the Zod schema which is also really handy to avoid duplication and have it automatically update when the userSchema is updated.
Zod provides detailed validation messages which can also be customised like so:
const name = z.string({
required_error: "Name is required",
invalid_type_error: "Name must be a string",
});
Conclusion
Zod is a great tool to write cleaner and simpler code for validation. Share your experiences with these tools in the comments.