JavaScript Object Validators

Data validation libraries are designed for validating data at runtime, so it throws or returns detailed runtime errors for you or your end users. This is especially useful in situations like accepting arbitrary input in a REST or GraphQL API. It can even be used to validate internal data structures at runtime when needed.

Instead of having your data validation and sanitization logic written as lengthy code, you can declare the requirements to your data with concise easy to read cross-platform schemas and validate the data as soon as it arrives to your application.

Popular libraries

Joi (20k ⭐) -> The most powerful schema description language and data validator for JavaScript. Joi lets you describe your data using a simple, intuitive, and readable language.

Zod (20k ⭐) -> A TypeScript-first schema declaration and validation library. Zod is designed to be as developer-friendly as possible. The goal is to eliminate duplicative type declarations. With Zod, you declare a validator once and Zod will automatically infer the static TypeScript type. It’s easy to compose simpler types into complex data structures.

Validator.js (21k ⭐) -> This library validates and sanitizes strings only, validate all sorts of concerns related to string and convert if possible.

Yup (20k ⭐) -> schema builder for runtime value parsing and validation. Define a schema, transform a value to match, assert the shape of an existing value, or both. Yup schema are extremely expressive and allow modeling complex, interdependent validations, or value transformation.

Ajv (12k ⭐) -> A JSON Schema validator for Node.js and browser, implements full JSON Schema, asynchronous loading of referenced schemas during compilation, etc.

Superstruct (6k ⭐) -> Makes it easy to define interfaces and then validate JavaScript data against them. Its type annotation API was inspired by Typescript, Flow, Go, and GraphQL, giving it a familiar and easy to understand API.

Common features

Validating data at runtime. Ensuring that it matches a specific schema, throws (or returns) detailed runtime errors for you or your end users.

Coercing data. Sometimes while validating input data you’ll actually want to “coerce” it to change it in someway to help validation pass. The most common example of this is adding default values to properties, but it can also be used to parse multiple input formats, or cleanup inconsistent data.

Handling errors. You’ll get nice errors messages that help you track down why a piece of data is invalid. You can also specify your own message for more clarity.

Working with TypeScript. Infer static types from schema, or ensure schema correctly implement a type.

Extensible: Add your own type-safe methods and schema.


Schema definitions, are comprised of parsing “transforms” which manipulate inputs into the desired shape and type, “tests”, which make assertions over parsed data. Schema also store a bunch of “metadata”, details about the schema itself, which can be used to improve error messages, build tools that dynamically consume schema, or serialize schema into another format.

import { object, string, number, date, InferType } from 'yup';

let userSchema = object({
  name: string().required(),
  age: number().required().positive().integer(),
  email: string().email(),
  website: string().url().nullable(),
  createdOn: date().default(() => new Date()),

// parse and assert validity
const user = await userSchema.validate(await fetchUser());

A schema’s default is used when casting produces an undefined output value. Because of this, setting a default affects the output type of the schema.