Zod: A Data Validation Library

Introduction to Zod

Zod is a powerful library for data validation in JavaScript and TypeScript. It helps ensure that your data meets certain criteria, making your applications more robust and error-free.

Why Use Zod?

  • Type Safety: Ensures that data conforms to specific types.

  • Validation: Checks that data meets certain rules (e.g., an email must be in a valid email format).

  • Error Handling: Provides detailed error messages.

  • Flexibility: Can be used in various scenarios like form validation, API response validation, etc.

Installation

First, let's install Zod using npm or yarn.

npm install zod

or

yarn add zod

Basic Usage

Let's start with a simple example. Suppose we want to validate user data that includes a name, age, and email.

  1. Import Zod:

      const { z } = require('zod');
    
  2. Define a Schema:

    A schema is a blueprint that defines the structure and validation rules for your data.

      const userSchema = z.object({
        name: z.string().min(1, 'Name is required'),
        age: z.number().int().positive('Age must be a positive integer'),
        email: z.string().email('Invalid email address'),
      });
    
  3. Validate Data:

    Use the schema to validate data.

      const result = userSchema.safeParse({
        name: "John Doe",
        age: 30,
        email: "john.doe@example.com",
      });
    
      if (result.success) {
        console.log('Data is valid:', result.data);
      } else {
        console.error('Validation errors:', result.error.errors);
      }
    

Using Zod with Express

Zod can be very useful in validating request data in an Express application. Let’s see how to do this.

  1. Setup Express:

      const express = require('express');
      const { z } = require('zod');
    
      const app = express();
      app.use(express.json());
    
  2. Define a Schema:

    We’ll use the same user schema from above.

  3. Validate Request Data:

      app.post('/users', (req, res) => {
        const result = userSchema.safeParse(req.body);
    
        if (!result.success) {
          return res.status(400).json({ errors: result.error.errors });
        }
    
        res.status(201).json(result.data);
      });
    
      app.listen(3000, () => {
        console.log('Server is running on port 3000');
      });
    

Advanced Features

Nested Objects

Zod can handle complex nested structures.

const addressSchema = z.object({
  street: z.string(),
  city: z.string(),
  postalCode: z.string().regex(/^\d{5}(-\d{4})?$/, 'Invalid postal code'),
});

const userSchema = z.object({
  name: z.string(),
  age: z.number().int().positive(),
  email: z.string().email(),
  address: addressSchema,
});

Arrays and Tuples

const stringArraySchema = z.array(z.string());

const tupleSchema = z.tuple([z.string(), z.number(), z.boolean()]);

Unions and Enums

const statusSchema = z.union([z.literal('success'), z.literal('error')]);
const exampleUnion = z.union([z.string(), z.number()]);

const roleSchema = z.enum(['admin', 'user', 'guest']);

Custom Validation

You can add custom validation logic.

const passwordSchema = z.string().min(8).max(20).refine((val) => /[A-Z]/.test(val), {
  message: "Password must contain at least one uppercase letter",
});

Using Middleware for Validation

To keep our code clean, we can use middleware for validation.

  1. Create Middleware:

      const validateSchema = (schema) => (req, res, next) => {
        const result = schema.safeParse(req.body);
        if (!result.success) {
          return res.status(400).json({ errors: result.error.errors });
        }
        req.validatedBody = result.data;
        next();
      };
    
  2. Apply Middleware:

      app.post('/users', validateSchema(userSchema), (req, res) => {
        res.status(201).json(req.validatedBody);
      });
    

Summary

  • Installation: Install Zod using npm or yarn.

  • Schema Definition: Define schemas to specify the structure and validation rules of your data.

  • Validation: Use schemas to validate data and handle errors.

  • Integration with Express: Validate request data in Express applications.

  • Advanced Features: Handle nested objects, arrays, tuples, unions, enums, and custom validation logic.

  • Middleware: Use middleware for clean and reusable validation logic.

Practice Exercises

  1. Simple Validation: Create a schema to validate a product object with name, price, and category.

  2. API Validation: Create an Express route to validate and handle a POST request for creating a new product.

  3. Advanced Schema: Create a schema for a blog post that includes a title, content, author, and an array of tags.

0
Subscribe to my newsletter

Read articles from Muhammad Kamil Raza directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Muhammad Kamil Raza
Muhammad Kamil Raza