Learn / Frameworks / Express / Validation with Zod

Express · Lesson 5 of 15

Validation with Zod

Parse params, query and body with a schema and return 400s that clients can use.

  • Beginner
  • 14 min read
  • 3 objectives

Before this lessonLesson 4: Databases and Authentication

What you will learn

  • Validate a body
  • Reuse a schema
  • Fail closed on extra fields

Your Progress

0 of 15 lessons 0%

  • Lessons0 / 15
  • Completed0
  • Est. time left~ 4 hours

Create a free account to keep your progress on every device.

Hand-rolled if (!title) checks drift. A schema library such as zod parses and types the input, and gives the client a list of field errors.

A reusable helper

import { z } from "zod";

export function validate(schema) {
  return (req, res, next) => {
    const parsed = schema.safeParse({
      body: req.body,
      params: req.params,
      query: req.query,
    });
    if (!parsed.success) {
      return res.status(400).json({ errors: parsed.error.flatten() });
    }
    req.valid = parsed.data;
    next();
  };
}

Using it

const CreateTask = z.object({
  body: z.object({
    title: z.string().trim().min(1).max(100),
    done: z.boolean().optional(),
  }),
});

app.post("/tasks", validate(CreateTask), (req, res) => {
  const { title, done = false } = req.valid.body;
  res.status(201).json({ id: 1, title, done });
});

Params and query

const GetTask = z.object({
  params: z.object({ id: z.coerce.number().int().positive() }),
  query: z.object({ include: z.enum(["author"]).optional() }),
});
Up next · Lesson 6Async Errors and Central HandlersWrap async routes, throw http-errors and keep a single error middleware.