io-ts

A TypeScript runtime type system that derives static types and runtime decoders/encoders from one composable schema.

Library
npm
v2.2.22
6,809stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
50/100Fair
Development Activity0
Maintenance44
Community56
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
72/100Good
Architecture80
Code Quality78
Innovation75
Learning Curve55

io-ts lets you define a value’s shape once, as a composable Codec/Type, and get both a static TypeScript type (via t.TypeOf<>) and a runtime decoder that validates unknown input (like JSON from an API) against that shape. Because TypeScript types are erased at compile time, plain interface/type declarations can’t check data arriving from outside your program — io-ts closes that gap by making the schema the single source of truth for both compile-time and runtime checks.

It’s built on fp-ts functional programming primitives (Either, pipeable operators) so validation failures are represented as typed errors rather than thrown exceptions, and the library supports refinements, unions, intersections, recursive types, branded types, and custom codecs for values that plain structural typing can’t express.

What You Get

  • Composable Codec/Type primitives (string, number, array, type, union, intersection, etc.)
  • t.TypeOf<C> to derive a static TypeScript type directly from a runtime codec
  • Decode/encode functions returning fp-ts Either values instead of throwing on invalid input
  • Support for refinements, branded types, recursive types, and custom codecs for values structural typing can’t express
  • PathReporter/ThrowReporter helpers for formatting validation errors into human-readable messages
  • A newer Decoder/Encoder/Codec module split for more granular decode/encode-only use cases

Common Use Cases

  • Validating JSON payloads from an external API or webhook before trusting their shape in application code
  • Parsing and validating environment variables or configuration files with a single schema shared across code and docs
  • Deriving TypeScript types directly from validation schemas to avoid keeping a hand-written interface in sync
  • Building typed, composable request/response validators for a Node.js API layer without a separate JSON Schema

Under The Hood

Architecture io-ts models a runtime value shape as a Type<A, O, I> object combining a is type guard, validate/decode function, and encode function; combinators like t.type, t.union, and t.array compose smaller Type instances into larger ones, and t.TypeOf<typeof MyType> extracts the corresponding static TypeScript type via conditional types, so schema and type stay mechanically in sync. Tech Stack It’s a TypeScript library with fp-ts as its only runtime dependency, providing the Either/functional-error-handling primitives that decode/validate results are expressed in; it ships both CommonJS (lib/) and ES module (es6/) builds plus full type declarations. Code Quality The codebase is organized as many focused modules (Decoder.ts, Encoder.ts, Codec.ts, Guard.ts, Eq.ts, DecodeError.ts) each covering one concern, with an extensive test/ suite, dtslint type-level tests, ESLint, and Prettier all wired into the npm test script — reflecting a mature, well-tested library, though release activity has slowed in recent years. API Design The API favors small composable primitives over a single monolithic schema builder, which gives strong compositionality but has a steeper learning curve for developers unfamiliar with fp-ts’s functional style (Either, pipe); the newer Decoder/Encoder split further separates concerns at the cost of an extra concept to learn.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search