Skip to main content

Type-safe validation for TypeScript

Elegant and battle-tested validation library that provides runtime type checking with automatic TypeScript type inference

import { object, string, number, array } from 'decoders';

const userDecoder = object({
  id: number,
  name: string,
  tags: array(string),
});

const user = userDecoder.verify(externalData);
//    ^? { id: number; name: string; tags: string[] }

Why decoders?

Build robust TypeScript applications with confidence using validation that catches errors at runtime

Type inference

Automatic TypeScript type inference from your decoder definitions

Composable

Build complex validators from simple, reusable building blocks

Zero dependencies

Tiny bundle size with zero runtime dependencies and full tree-shaking support

Excellent errors

Detailed error messages that pinpoint exactly what went wrong

Battle-tested

Used in production by thousands of projects with comprehensive test coverage

Cross-platform

Works everywhere: Node.js, browsers, Bun, Deno, and Cloudflare Workers

Quick start

Get up and running with decoders in minutes

1

Install the package

Install decoders using your preferred package manager:
npm install decoders
Make sure you have "strict": true in your tsconfig.json for proper type inference.
2

Import and create a decoder

Define your data structure using decoder functions:
import { object, string, number, optional, array } from 'decoders';

const userDecoder = object({
  id: number,
  name: string,
  email: optional(string),
  roles: array(string),
});
The decoder describes the shape and types of the data you expect.
3

Validate untrusted data

Use .verify() to validate data and get type-safe results:
// Data from external source (API, user input, etc.)
const externalData = {
  id: 123,
  name: 'Alice',
  roles: ['admin', 'user'],
};

// Validate and get type-safe result
const user = userDecoder.verify(externalData);
// TypeScript knows: { id: number; name: string; email?: string; roles: string[] }

console.log(user.name); // 'Alice'
If validation fails, .verify() throws an error with a detailed message.
4

Handle validation errors

For non-throwing validation, use .decode() to get a result object:
const result = userDecoder.decode(externalData);

if (result.ok) {
  console.log('Valid user:', result.value);
} else {
  console.error('Validation failed:', result.error);
}
The result object follows a discriminated union pattern for safe error handling.

Resources

Additional resources to help you get the most out of decoders

GitHub repository

View the source code, report issues, and contribute to the project

Migration guide

Upgrading from v1? Learn how to migrate your existing code to v2

Ready to build type-safe applications?

Get started with decoders and add runtime validation to your TypeScript projects today

Build docs developers (and LLMs) love