Zod parse with custom error in Express

Photo by Sarah Kilian on Unsplash

If you use Typescript then zod is a great data parser to try. Here is a quick method that will allow you to return a custom error message when a zod parser fails to parse a schema.

Add type definitions

Add a folder called "type-definitions" to your project. In that folder create a file called "express.d.ts". This is where you will put your custom types.

Save the following to zod-parse.ts:

import type { Request } from "express";
import { AnyZodObject, ZodError, z } from "zod";
import { BadRequestError } from "./bad-request-error.js";

export async function zParse<T extends AnyZodObject>(
  schema: T,
  req: Request
): Promise<z.infer<T>> {
  try {
    // have to await this here to convert this error to a BadRequestError
    return await schema.parseAsync(req);
  } catch (error) {
    if (error instanceof ZodError) {
      throw new BadRequestError(error.message);
    }
    throw new BadRequestError(JSON.stringify(error));
  }
}

And now use it in your routes like this:

import { z } from "zod";
import { zParse } from "../zod-parse.ts";

export const handleSomeRequest = (req, res, done) => {
  const schema = z.object({
    name: z.string().min(3).max(255),
    email: z.string().email(),
    password: z.string().min(8).max(255),
  });

  // this will throw a BadRequestError if the schema fails to parse
  // The result is a perfectly typed object
  const { name, email, password } = await zParse(schema, req);

  // do something with the data
};

This is a nice way to convert Express request.body data into a typed object. If the data fails to parse then a BadRequestError is thrown with a custom error message.

I hope this helps!