Data Validation in TypeScript: Zod, Yup, and Other Tools

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Data Validation in TypeScript: Overview of Tools and Practices



In modern web development with TypeScript, one of the key tasks is ensuring data integrity. Even with strict static typing, TypeScript cannot guarantee that data coming from the outside world (API, forms, localStorage) matches the expected format. This is where runtime validation comes to the rescue — checking data during program execution. In this article, we will look at three popular libraries: Zod, Yup, and Joi, compare their approaches, and show how to integrate validation into a TypeScript project.



Why Are Simple TypeScript Types Not Enough?

TypeScript checks types at compile time, but at runtime all annotations are erased. This means that:

  • User data may contain extra fields or lack required ones
  • Numbers may come as strings
  • Objects may be null or undefined

Validation libraries solve this problem by providing schemas that work both as validation and type inference.



1. Zod — The Modern Standard

Zod is the most popular library for validation in TypeScript. Its main advantage is automatic TypeScript type inference from schemas.



Installation

npm install zod


Basic Schema Example

import { z } from 'zod';

const UserSchema = z.object({ id: z.number().positive(), name: z.string().min(2).max(50), email: z.string().email(), age: z.number().int().min(18).optional(),});

// Type inference: { id: number; name: string; email: string; age?: number }type User = z.infer<typeof UserSchema>;

// Validationconst result = UserSchema.safeParse(inputData);if (!result.success) { console.error(result.error.errors);} else { // result.data — valid data with type User processUser(result.data);}


Advanced Features

  • Transformation: z.string().transform(val => val.trim())
  • Discriminated Unions: z.discriminatedUnion('type', [...])
  • Recursive Schemas: z.lazy(() => NodeSchema)
  • Custom Errors: z.string().refine(val => !val.includes('bad'), 'Cannot use the word bad')


2. Yup — A Time-Tested Tool

Yup is a library with a rich history, originally created for form validation. It integrates well with Formik and React Hook Form.



Installation

npm install yup


Schema Example

import * as yup from 'yup';

const productSchema = yup.object({ title: yup.string().required('Title is required').min(3), price: yup.number().positive('Price must be positive').required(), inStock: yup.boolean().default(true),});

type Product = yup.InferType<typeof productSchema>;

// ValidationproductSchema.validate(inputData, { abortEarly: false }) .then(validData => console.log(validData)) .catch(err => console.error(err.errors));


Yup Features

  • Support for conditional validation: .when('field', ...)
  • Built-in error messages in Russian (when locale is configured)
  • Easy work with nested objects and arrays
  • cast() and transform() methods for type coercion


3. Joi — Powerful but Heavier

Joi is a legendary library from the Node.js ecosystem (Hapi.js). It provides maximum flexibility but does not have built-in TypeScript integration (requires manual type definitions).



Installation

npm install joi @types/joi<                    

Recommendations