Basics of Zod
What is Zod?
Zod is a TypeScript-first schema validation library.
You define what data should look like:
import { z } from "zod";
const User = z.object({
name: z.string(),
age: z.number(),
});
Then validate data:
const result = User.safeParse(data);
Basic Types
z.string();
z.number();
z.boolean();
z.bigint();
z.date();
z.undefined();
z.null();
Example:
const name = z.string();
name.parse("Marvin"); // "Marvin"
name.parse(123); // throws
Objects
const User = z.object({
username: z.string(),
age: z.number(),
active: z.boolean(),
});
User.parse({
username: "marvin",
age: 25,
active: true,
});
Optional Fields
const User = z.object({
username: z.string(),
bio: z.string().optional(),
});
bio can be missing.
Nullable Fields
const User = z.object({
bio: z.string().nullable(),
});
bio must exist, but can be null.
Arrays
const Tags = z.array(z.string());
Tags.parse(["js", "typescript", "zod"]);
Enums
const Role = z.enum(["user", "admin"]);
Role.parse("admin"); // "admin"
Constraints
const Password = z.string().min(8).max(100);
const Age = z.number().int().min(18).max(120);
Parsing
parse()
Throws if invalid:
const user = User.parse(data);
Good when invalid input should immediately become an exception.
safeParse()
Doesn’t throw:
const result = User.safeParse(data);
if (!result.success) {
console.log(result.error);
} else {
console.log(result.data);
}
Useful for HTTP request validation.
Transform
You can transform validated data:
const Email = z
.string()
.email()
.transform((email) => email.toLowerCase());
Email.parse("USER@EXAMPLE.COM");
// "user@example.com"
Infer TypeScript Types
Zod can generate a TypeScript type from a schema:
const User = z.object({
name: z.string(),
age: z.number(),
});
type User = z.infer<typeof User>;
Equivalent to:
type User = {
name: string;
age: number;
};
Schema = runtime validation
z.infer = compile-time type
Common HTTP Pattern
For a POST endpoint:
const Signup = z.object({
email: z.string().email(),
password: z.string().min(8),
});
const result = Signup.safeParse(await c.req.json());
if (!result.success) {
return c.json({ error: "Invalid input" }, 400);
}
const data = result.data;
Now data is validated.
Useful Methods
.optional()
.nullable()
.array()
.min()
.max()
.length()
.email()
.url()
.uuid()
.int()
.regex()
.refine()
.transform()
Mental Model
Untrusted data
↓
Zod
↓
validated data
↓
application
For web applications:
HTTP request
↓
JSON
↓
Zod schema
↓
validation
↓
database / business logic
Main rule: validate data at the boundary before trusting it.