1garo's blog

Why you should use zod as your validator?

- 3 min

Why you should use zod as your validator?

The title is just to bring some attention… I know, you use what you want, but today I’ll be giving some insights on zod, from someone that is using it daily for the last 6-8 months.

To keep it simple, I’m gonna omit most of the express app setup because it’s kinda easy to do, however you can find it in their documentation.


Installation

$ npm i zod express typescript body-parser
$ npm i -g npx
$ npx tsc --init
$ npm i --save-dev @types/express

Practical examples

Let’s say that you have an express api with a /user endpoint.

// src/index.ts
import express, { Express } from 'express';
import bodyParser from 'body-parser';

import User from './controller/user.controller';

const app: Express = express();

// parse application/json
app.use(bodyParser.json())

app.post('/user', User.create);

app.listen(3000, () => {
  console.log(`⚡️[server]: Server is running at http://localhost:${3000}`);
});

You usually would do something like:

// controller/user.controller.ts
import { Request, Response } from 'express';

const User = (() => {
    const create = async (req: Request, res: Response) => {
        const { name, age } = req.body;

        // ...

        return res.send({ name, age })
    }

    return {
        create,
    }
})();


export default User;

But as we can see, we lack typing inference, type validation, and a lot of other things.

Also you could say something like:

1garo, you are wrong, I know better!.

// controller/user.controller.ts

import { CreateUser } from '@/types/user.typings

/// ...
const { name, age } = req.body as CreateUser;

Well, you are right! Kinda…

I just don’t wanna be there when the user sends something wrong (and he WILL! I ensure you of that).

Let me show you the zod way!

One of the things that I really like about zod is this “composition” approach. It makes me feel that I’m writing in a functional language and it’s very easy to use, so let’s solve the problem that we had discussed.

We have to describe our schema, the one to be validated.

// src/validation/user.validation.ts
import z from 'zod';

export const userValidation = z.object({
  name:
  z.string()
    .min(1, { message: "Must be 1 or more characters long" })
    .trim(),
  age:
  z.number()
    .gte(18)
    .int()
    .positive()
});

Now back to the last example and let’s use our new validator.

- const { name, age } = req.body as CreateUser;
+ const { name, age } = await userValidation.parse(req.body);

Yeahhhh, We did it! Now your input is type safe and has inference.


I just showed you a tiny bit about what zod can do, but you can check it out more here.

My favorite functionalities are: .refine(), .transform(), and .partial(). Maybe I could write another post using those features, I think it could be fun!

See u on the next episode.