All posts

Beginner Zod: Introduction to Schema Validation

10 min read

What is Zod?

Zod is a TypeScript-first schema declaration and validation library that helps you create robust type definitions and validate complex data structures with ease. Unlike traditional validation libraries, Zod provides type safety and inference out of the box.

Why Choose Zod?

Zod solves several common challenges in TypeScript development:

  • Provides runtime type checking
  • Generates TypeScript types automatically
  • Offers a declarative and intuitive API for schema validation
  • Minimizes boilerplate code
  • Works seamlessly with TypeScript's static type system

Getting Started

Integrating Zod into your TypeScript project is straightforward and can significantly improve your data validation workflow. This section will guide you through the initial setup and help you understand the basic concepts of getting started with Zod.

Installation

Before you begin, ensure you have a TypeScript project set up. Zod is compatible with various package managers, giving you flexibility in your development environment:

bash
npm install zod

Importing Zod

After installation, import Zod into your project:

ts
// Most developers prefer using a simple import: import { z } from "zod";

Project Integration

Zod can be integrated into various parts of your application:

  • Form validation
  • API request/response validation
  • Configuration parsing
  • Data transformation
  • Runtime type checking

Compatibility

Zod works with:

  • Node.js projects
  • Browser-based applications
  • Server-side rendering frameworks
  • Client-side frameworks like React, Vue, and Angular

Basic Usage

Understanding primitive schemas is the foundation of working with Zod. Primitive schemas allow you to define and validate basic data types, ensuring type safety and preventing unexpected data inconsistencies in your application.

Primitives

String

String schemas provide comprehensive validation for text-based inputs:

tsx
const nameSchema = z.string(); // Validation examples nameSchema.parse("John"); // ✅ Valid nameSchema.parse(123); // ❌ Throws validation error nameSchema.parse(""); // ✅ Valid (empty string)
Number

Number schemas ensure numeric type safety and allow for range constraints:

tsx
// Basic number schema const ageSchema = z.number(); // Validation examples ageSchema.parse(25); // ✅ Valid ageSchema.parse("25"); // ❌ Throws validation error ageSchema.parse(NaN); // ❌ Throws validation error
Boolean

Boolean schemas ensure boolean type safety:

tsx
// Basic boolean schema const isActiveSchema = z.boolean(); // Validation examples isActiveSchema.parse(true); // ✅ Valid isActiveSchema.parse(false); // ✅ Valid isActiveSchema.parse(0); // ❌ Throws validation error
Date

Date schemas ensure date type safety and allow for range constraints:

tsx
// Date schema const dateSchema = z.date(); dateSchema.parse(new Date()); // Valid dateSchema.parse("2024-01-01"); // Throws validation error

Demo

Here's a simple demo of how to use Zod to validate a string:

Input:

Result:

Invalid input

Adding Constraints

Adding constraints to your schemas is a powerful way to ensure data integrity and prevent invalid data from being processed. Here are some examples:

tsx
// String with length constraints const usernameSchema = z .string() .min(3, { message: "Username must be at least 3 characters" }) .max(20, { message: "Username cannot exceed 20 characters" }); // Number with range constraints const scoreSchema = z .number() .min(0, { message: "Score cannot be negative" }) .max(100, { message: "Score cannot exceed 100" });

Demo

Here's a simple demo of how to use Zod to validate a string with constraints:

Input:

Result:

Parsing vs. SafeParse

Zod provides two primary methods for validation: parse() and safeParse().

Choose parse() when you want to handle validation errors through try/catch blocks, which is useful in scenarios where you want to immediately stop execution and handle the error at a higher level.

Use safeParse() when you need more granular control over validation results and want to handle success/failure cases explicitly without try/catch blocks - this is particularly useful in form validations or API input parsing where you need to examine the specific validation details.

tsx
// Throws an error if validation fails try { const result = nameSchema.parse("Alice"); console.log(result); // 'Alice' } catch (error) { console.error("Validation failed"); }

Type Inference

One of Zod's most powerful and useful features is its ability to automatically infer TypeScript types from your schema definitions, eliminating the need to maintain separate type declarations:

tsx
const userSchema = z.object({ name: z.string(), age: z.number().optional(), }); // TypeScript knows the exact shape of the object type User = z.infer<typeof userSchema>; // Equivalent to: { name: string, age?: number }
note

TypeScript will infer the exact shape of the object from the schema:

ts
const userSchema: z.ZodObject< { name: z.ZodString; age: z.ZodOptional<z.ZodNumber>; }, "strip", z.ZodTypeAny, { name: string; age?: number | undefined; }, { name: string; age?: number | undefined; } >;

Demo

Common Validation Patterns

Here are some common validation patterns you can use with Zod to ensure data integrity and enforce business rules in your applications. These patterns cover the most frequently used validation scenarios and can be combined to create more complex validation rules:

tsx
// Email validation const emailSchema = z.string().email();

Error Handling

Zod provides detailed error information:

tsx
try { const result = emailSchema.parse("invalid-email"); } catch (error) { if (error instanceof z.ZodError) { console.log(error.errors); // Detailed error information } }

By leveraging Zod in your projects, you can create type-safe, robust validation schemas with minimal boilerplate code. In the next article of this series, we'll dive deeper into more complex validation techniques and advanced schema creation.


  • Zod
  • Schema Validation
  • TypeScript
  • Beginner
Made with ❤️ in 🇨🇦 · Copyright © 2025 Valentin Prugnaud
Foxy seeing you here! Let's chat!
Logo