typedecode
v1.0.3
Published
Type-safe runtime validation for TypeScript — parse untrusted input with precise inferred types
Downloads
474
Maintainers
Readme
typedecode
Version 1.0.3 — Type-safe runtime validation for TypeScript.
Turn untrusted data into typed values you can trust. Define a schema once, get full TypeScript inference, and validate at runtime with clear error messages.
Install
npm install typedecodeRequirement: enable strict mode in your tsconfig.json for correct type inference.
{
"compilerOptions": {
"strict": true
}
}Quick start
import { array, isoDate, number, object, optional, string } from 'typedecode';
const externalData = {
id: 123,
name: 'Alison Roberts',
createdAt: '2026-01-11T12:26:37.024Z',
tags: ['foo', 'bar'],
};
const userSchema = object({
id: number,
name: string,
createdAt: optional(isoDate),
tags: array(string),
});
const user = userSchema.verify(externalData);
// Inferred type:
// {
// id: number;
// name: string;
// createdAt?: Date;
// tags: string[];
// }Core concepts
Schemas
Every validator in typedecode is a schema — a reusable description of the shape you expect. Built-in schemas cover strings, numbers, booleans, dates, arrays, objects, unions, and more.
Three ways to validate
| Method | Behavior |
|--------|----------|
| .verify(input) | Returns the typed value, or throws a Validation error |
| .decode(input) | Returns { ok: true, value } or { ok: false, error } — never throws |
| .value(input) | Returns the typed value, or undefined on failure |
Compose and extend
Chain, transform, refine, and pipe schemas to build complex validators from simple ones:
import { define, email, string } from 'typedecode';
const username = string
.refine((s) => s.length >= 3, 'Username must be at least 3 characters')
.transform((s) => s.toLowerCase());
const contact = string.pipe((s) => (s.includes('@') ? email : username));Custom schemas
Use define() when you need full control:
import { define } from 'typedecode';
const evenNumber = define((blob, ok, err) =>
typeof blob === 'number' && blob % 2 === 0
? ok(blob)
: err('Must be an even number'),
);Standard Schema
typedecode schemas implement the Standard Schema interface via the ~standard property, so they work with ecosystem tools that support it.
Built-in schemas
| Category | Schemas |
|----------|---------|
| Primitives | string, number, integer, boolean, bigint, date |
| Strings | email, url, uuid, regex, nonEmptyString, identifier |
| Collections | array, tuple, record, object, exact, inexact |
| Unions | either, oneOf, enum_, taggedUnion, select |
| Modifiers | optional, nullable, nullish, constant, unknown |
| JSON | json, jsonObject, jsonArray |
Import everything from the package root:
import { number, object, string } from 'typedecode';Type inference
Extract the output type of any schema with SchemaType:
import type { SchemaType } from 'typedecode';
import { object, string } from 'typedecode';
const person = object({ name: string });
type Person = SchemaType<typeof person>; // { name: string }Use isSchema() to check whether a value is a typedecode schema at runtime.
Error formatting
Customize validation errors with built-in formatters or your own:
import { formatInline, formatShort } from 'typedecode';
userSchema.verify(badData, formatShort);License
MIT
