What is io-ts and why is it needed?
io-ts is a library for TypeScript that solves one of the most painful problems in development with this language: the discrepancy between static types (at compile time) and actual data (at runtime). TypeScript is a wonderful tool, but its type system only works during development. When your application runs, all types are erased. If you receive data from an external API, from a form on a website, from localStorage, or from any other source not controlled by your compiler, you cannot be sure that the data matches the declared types.
This is where runtime validation comes to the rescue. io-ts allows you to define a data schema once and then use it for two purposes:
- Static typing (compile-time): TypeScript infers types based on your schema, ensuring code safety at the time of writing.
- Runtime validation: io-ts checks whether the actual data matches your schema and returns either a successful result or a detailed error.
The library is based on the concept of codecs. A codec is an object that knows how to decode (validate and transform) raw data into a TypeScript type and how to encode (serialize) that type back. This makes io-ts a powerful tool not only for validation but also for safe data serialization/deserialization.
Installation
io-ts is a library for the Node.js and browser ecosystems, so it is installed via npm (or yarn). Note that io-ts requires fp-ts as a peer dependency, as it uses functional concepts such as Either and Option.
npm install io-ts fp-tsOr, if you are using yarn:
yarn add io-ts fp-tsAfter installation, you can import the library into your project:
import * as t from 'io-ts';import { isRight, isLeft } from 'fp-ts/Either';Quick Start: First Example
Let's start with a simple example. Suppose we expect a user object with fields name (string) and age (number). Let's define a schema using io-ts and try to validate some data.
import * as t from 'io-ts';import { isRight, isLeft } from 'fp-ts/Either';
// 1. Define the schema (codec)const User = t.type({ name: t.string, age: t.number,});
// 2. Function to safely get the typetype User = t.TypeOf<typeof User>;
// 3. Data to validateconst validData = { name: 'Alice', age: 30 };const invalidData = { name: 'Bob', age: 'twenty' }; // age is a string, not a number
// 4. Validationconst result1 = User.decode(validData);const result2 = User.decode(invalidData);
console.log(isRight(result1)); // trueconsole.log(isLeft(result2)); // true
// 5. Extract the data (if validation passed)if (isRight(result1)) { const user: User = result1.right; console.log(user.name); // Alice}
// 6. Handle the errorif (isLeft(result2)) { console.error('Validation error:', result2.left); // Will output a list of errors, for example: // [ { value: 'twenty', context: [...], message: 'Invalid value "twenty" supplied to : { name: string, age: number }/age: number' } ]}In this example, we see the key pattern: decode returns Either<Errors, A> from the fp-ts library. Either is a container that can contain either an error (the left type) or a successful value (the right type). We check the result using the isRight and isLeft functions.
Main Methods and Functions of io-ts
io-ts provides
Also in library
Reactive Programming in JavaScript (Node.js): RxJS Library
Working with XML in TypeScript: Libraries, Parsing, and Creating XML Documents
csv — Working with CSV Files in Rust
OAuth client for Node.js: implementing authorization via Google and GitHub
ts-functional-pipe for TypeScript: Complete Guide with Examples