TypeScript helps you prevent bugs at compile time, but it doesn't validate data coming from external sources like APIs, forms, or localStorage.
That's why Zod exists β to add runtime validation with static type inference.
Traditionally, developers rely on libraries like yup
or manual checks. But with TypeScript gaining popularity, Zod has become the go-to choice for schema validation that integrates deeply with static types.
Letβs explore what makes Zod so effective and how to use it in real-world projects.
π― What is zod?
Zod is a TypeScript-first schema validation library that:
- Parses and validates data
- Automatically infers static types
- Is zero-dependency and lightweight
It works in both JavaScript and TypeScript, but really shines in TypeScript projects.
π Why zod?
- β Validates at runtime
- β Infers static TypeScript types
- β No extra dependencies
- β Ideal for frontend, backend, or fullstack apps
π¦ Installation
npm install zod
π Basic example
import { z } from 'zod';
const UserSchema = z.object({
name: z.string(),
email: z.string().email(),
age: z.number().min(18),
});
// Runtime validation
const user = UserSchema.parse({
name: 'Pedro',
email: 'pedro@example.com',
age: 25,
});
If validation fails, Zod throws:
UserSchema.parse({ name: 'Pedro', email: 'not-email', age: 10 });
// β Throws detailed validation error
π§ Inferred types
Zod lets you reuse your schema as a type:
type User = z.infer<typeof UserSchema>;
This keeps types and validation perfectly in sync.
β¨ Safe parsing
To avoid exceptions, use safeParse
:
const result = UserSchema.safeParse(data);
if (!result.success) {
console.log(result.error.format());
} else {
// result.data is fully validated and typed
}
π Real-world use cases
1. Validating API requests
app.post('/signup', (req, res) => {
const result = UserSchema.safeParse(req.body);
if (!result.success) {
return res.status(400).json(result.error.flatten());
}
// req.body is now trusted
});
2. Parsing config or localstorage
const Settings = z.object({
darkMode: z.boolean().optional(),
});
const raw = localStorage.getItem('settings');
const parsed = Settings.safeParse(JSON.parse(raw ?? '{}'));
β Conclusion
Zod adds a missing layer to TypeScript: runtime safety.
You canβt trust external data just because your types say itβs valid β Zod ensures it really is.
If you're building apps where data crosses boundaries, Zod is a no-brainer.