Zod — Runtime Type Validation for TypeScript

Sanjeev SharmaSanjeev Sharma
2 min read

Advertisement

Zod provides TypeScript-first runtime validation. Type safe at both compile and runtime.

Basic Schema

npm install zod
import { z } from "zod";

const userSchema = z.object({
  name: z.string(),
  email: z.string().email(),
  age: z.number().int().min(0).max(150),
});

// Type inferred from schema
type User = z.infer<typeof userSchema>;

const data = { name: "Alice", email: "alice@example.com", age: 30 };
const user = userSchema.parse(data); // Throws if invalid

Validation in Express

const createUserSchema = z.object({
  name: z.string().min(3),
  email: z.string().email(),
  password: z.string().min(8),
});

app.post("/users", (req, res) => {
  try {
    const data = createUserSchema.parse(req.body);
    const user = db.users.create(data);
    res.status(201).json(user);
  } catch (error) {
    if (error instanceof z.ZodError) {
      res.status(400).json({ errors: error.errors });
    }
  }
});

Advanced Schemas

// Optional fields
const schema = z.object({
  name: z.string(),
  bio: z.string().optional(),
});

// Custom validation
const passwordSchema = z.string().superRefine((val, ctx) => {
  if (!/[A-Z]/.test(val)) {
    ctx.addIssue({
      code: z.ZodIssueCode.custom,
      message: "Must contain uppercase",
    });
  }
});

// Discriminated union
const eventSchema = z.discriminatedUnion("type", [
  z.object({ type: z.literal("click"), x: z.number(), y: z.number() }),
  z.object({ type: z.literal("scroll"), y: z.number() }),
]);

FAQ

Q: Zod vs io-ts vs class-validator? A: Zod easiest, best TypeScript support. All work well.

Q: Can I compose schemas? A: Yes, use .extend() and .pick().


Zod makes runtime validation painless and type safe.

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro