tcomb: Runtime Type Checking & DDD

3.2.29 · active · verified Sun Apr 19

tcomb is a JavaScript library for runtime type checking and Domain-Driven Design (DDD), suitable for both Node.js and browser environments. It provides a concise syntax for defining and validating data structures, enhancing code safety during development. The current stable version is 3.2.29, with a recent cadence focused on bug fixes and TypeScript definition improvements. A key differentiator is its lightweight nature (3KB gzipped, no dependencies) and its foundation in set theory for type definition. It supports various type combinators (structs, lists, enums, refinements, unions), immutability helpers compatible with Facebook's Immutability Helpers, and runtime type introspection. Crucially, tcomb is designed to be *disabled in production* (its checks are stripped out for performance), with `io-ts` or `tcomb-validation` recommended for production-grade type validation.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to define type-checked functions, create custom refined types, build structured objects (structs) with runtime validation, and perform immutable updates on instances using tcomb's utilities.

import t from 'tcomb';

// A type-checked function demonstrating basic validation
function sum(a, b) {
  t.Number(a); // Runtime check: 'a' must be a Number
  t.Number(b); // Runtime check: 'b' must be a Number
  return a + b;
}

try {
  sum(1, 's'); // This will throw an error
} catch (e) {
  console.error(`Caught error for sum(1, 's'): ${e.message}`);
}

// Define a custom refined type (Integer)
const Integer = t.refinement(t.Number, (n) => n % 1 === 0, 'Integer');

// Define a structured object (a 'struct') for a Person
const Person = t.struct({
  name: t.String,              // required string
  surname: t.maybe(t.String),  // optional string (can be null or undefined)
  age: Integer,                // required integer (using our custom Integer type)
  tags: t.list(t.String)       // a list of strings
}, 'Person');

// Add a method to the struct's prototype (as you would with a class)
Person.prototype.getFullName = function () {
  return `${this.name} ${this.surname ?? ''}`.trim();
};

let personInstance;
try {
  personInstance = Person({
    name: 'Guido',
    age: 42,
    tags: ['developer', 'js']
  });
  console.log(`Created person: ${personInstance.getFullName()}`);
} catch (e) {
  console.error(`Caught error creating person: ${e.message}`);
}

// Attempt to create a person with missing required fields
try {
  Person({
    surname: 'Canti'
  }); // This will throw an error for missing 'name' and 'age'
} catch (e) {
  console.error(`Caught error for invalid person creation: ${e.message}`);
}

// Update an immutable instance using t.update
const updatedPerson = Person.update(personInstance, {
  name: { $set: 'Giuliano' }, // Change name
  age: { $set: 43 },          // Change age
  tags: { $push: ['opensource'] } // Add a tag
});
console.log(`Updated person: ${updatedPerson.getFullName()}, Age: ${updatedPerson.age}, Tags: ${updatedPerson.tags.join(', ')}`);

view raw JSON →