Zod integration
TypeScript · Reference cheat sheet
Zod integration
TypeScript · Reference cheat sheet
📋 Overview
Zod defines runtime schemas that infer TypeScript types (z.infer<typeof schema>). Use it at trust boundaries (HTTP, forms, env, JSON) instead of assertions. Patterns below target Zod 3.x with TS 5.x.
🔧 Core concepts
- Single source — schema →
z.infertype; avoid duplicating interfaces. - Parse vs safeParse — throw vs
\{ success, data | error \}. - Compose —
object,union,discriminatedUnion,array,optional,nullable. - Transforms —
.transform/.pipefor coercion and branding. - Shared — export schemas from a
packages/sharedorlib/schemasmodule.
💡 Examples
import { z } from "zod";
const UserSchema = z.object({
id: z.string().uuid(),
email: z.string().email(),
role: z.enum(["admin", "user"]),
age: z.number().int().positive().optional(),
});
type User = z.infer<typeof UserSchema>;
const raw: unknown = JSON.parse(body);
const user = UserSchema.parse(raw); // User or throw
const result = UserSchema.safeParse(raw);
if (!result.success) {
console.error(result.error.flatten());
} else {
console.log(result.data.email);
}
const ResultSchema = z.discriminatedUnion("ok", [
z.object({ ok: z.literal(true), value: z.string() }),
z.object({ ok: z.literal(false), error: z.string() }),
]);
const UserIdSchema = z.string().min(1).brand<"UserId">();
type UserId = z.infer<typeof UserIdSchema>;
// Env
const EnvSchema = z.object({
NODE_ENV: z.enum(["development", "test", "production"]),
PORT: z.coerce.number().default(9000),
});
const env = EnvSchema.parse(process.env);// Express / fetch handler
async function handler(req: Request) {
const json: unknown = await req.json();
const input = UserSchema.parse(json);
return Response.json(input);
}⚠️ Pitfalls
- Don’t
as Userafter partial checks — parse the full schema. .optional()vs.nullable()vs.nullish()— pick intentionally.z.coercecan hide bad input (e.g.Number("") === 0).- Huge nested schemas slow cold start — split and lazy-load if needed.
- Keep server and client schemas in sync via a shared package.