An open API service indexing awesome lists of open source software.

https://github.com/sinclairzx81/sinclair-typebox

Json Schema Type Builder with Static Type Resolution for TypeScript
https://github.com/sinclairzx81/sinclair-typebox

support typebox

Last synced: 2 months ago
JSON representation

Json Schema Type Builder with Static Type Resolution for TypeScript

Awesome Lists containing this project

README

          

Sinclair TypeBox

Json Schema Type Builder with Static Type Resolution for TypeScript




[![npm version](https://badge.fury.io/js/%40sinclair%2Ftypebox.svg)](https://badge.fury.io/js/%40sinclair%2Ftypebox)
[![Downloads](https://img.shields.io/npm/dm/%40sinclair%2Ftypebox.svg)](https://www.npmjs.com/package/%40sinclair%2Ftypebox)
[![Build](https://github.com/sinclairzx81/typebox/actions/workflows/build.yml/badge.svg)](https://github.com/sinclairzx81/typebox/actions/workflows/build.yml)
[![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Install

For the latest version use [TypeBox 1.x](https://github.com/sinclairzx81/typebox)

```bash
$ npm install @sinclair/typebox # TypeBox 0.x - Long Term Support

$ npm install typebox # TypeBox 1.x - Latest
```

## Example

```typescript
import { Type, type Static } from '@sinclair/typebox'

const T = Type.Object({ // const T = {
x: Type.Number(), // type: 'object',
y: Type.Number(), // required: ['x', 'y', 'z'],
z: Type.Number() // properties: {
}) // x: { type: 'number' },
// y: { type: 'number' },
// z: { type: 'number' }
// }
// }

type T = Static // type T = {
// x: number,
// y: number,
// z: number
// }
```

## Overview

TypeBox is a runtime type builder that creates in-memory Json Schema objects that infer as TypeScript types. The schematics produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox offers a unified type that can be statically checked by TypeScript and runtime asserted using standard Json Schema validation.

This library is designed to allow Json Schema to compose similar to how types compose within TypeScript's type system. It can be used as a simple tool to build up complex schematics or integrated into REST and RPC services to help validate data received over the wire.

License MIT

## Contents
- [Install](#install)
- [Overview](#overview)
- [Usage](#usage)
- [Types](#types)
- [Json](#types-json)
- [JavaScript](#types-javascript)
- [Options](#types-options)
- [Properties](#types-properties)
- [Generics](#types-generics)
- [Recursive](#types-recursive)
- [Modules](#types-modules)
- [Template Literal](#types-template-literal)
- [Indexed](#types-indexed)
- [Mapped](#types-mapped)
- [Conditional](#types-conditional)
- [Transform](#types-transform)
- [Guard](#types-guard)
- [Unsafe](#types-unsafe)
- [Values](#values)
- [Assert](#values-assert)
- [Create](#values-create)
- [Clone](#values-clone)
- [Check](#values-check)
- [Convert](#values-convert)
- [Default](#values-default)
- [Clean](#values-clean)
- [Cast](#values-cast)
- [Decode](#values-decode)
- [Encode](#values-decode)
- [Parse](#values-parse)
- [Equal](#values-equal)
- [Hash](#values-hash)
- [Diff](#values-diff)
- [Patch](#values-patch)
- [Errors](#values-errors)
- [Mutate](#values-mutate)
- [Pointer](#values-pointer)
- [Syntax](#syntax)
- [Create](#syntax-create)
- [Parameters](#syntax-parameters)
- [Generics](#syntax-generics)
- [Options](#syntax-options)
- [NoInfer](#syntax-no-infer)
- [TypeRegistry](#typeregistry)
- [Type](#typeregistry-type)
- [Format](#typeregistry-format)
- [TypeCheck](#typecheck)
- [Ajv](#typecheck-ajv)
- [TypeCompiler](#typecheck-typecompiler)
- [TypeMap](#typemap)
- [Usage](#typemap-usage)
- [TypeSystem](#typesystem)
- [Policies](#typesystem-policies)
- [Error Function](#error-function)
- [Workbench](#workbench)
- [Codegen](#codegen)
- [Ecosystem](#ecosystem)
- [Benchmark](#benchmark)
- [Compile](#benchmark-compile)
- [Validate](#benchmark-validate)
- [Compression](#benchmark-compression)
- [Contribute](#contribute)

## Usage

The following shows general usage.

```typescript
import { Type, type Static } from '@sinclair/typebox'

//--------------------------------------------------------------------------------------------
//
// Let's say you have the following type ...
//
//--------------------------------------------------------------------------------------------

type T = {
id: string,
name: string,
timestamp: number
}

//--------------------------------------------------------------------------------------------
//
// ... you can express this type in the following way.
//
//--------------------------------------------------------------------------------------------

const T = Type.Object({ // const T = {
id: Type.String(), // type: 'object',
name: Type.String(), // properties: {
timestamp: Type.Integer() // id: {
}) // type: 'string'
// },
// name: {
// type: 'string'
// },
// timestamp: {
// type: 'integer'
// }
// },
// required: [
// 'id',
// 'name',
// 'timestamp'
// ]
// }

//--------------------------------------------------------------------------------------------
//
// ... then infer back to the original static type this way.
//
//--------------------------------------------------------------------------------------------

type T = Static // type T = {
// id: string,
// name: string,
// timestamp: number
// }

//--------------------------------------------------------------------------------------------
//
// ... or use the type to parse JavaScript values.
//
//--------------------------------------------------------------------------------------------

import { Value } from '@sinclair/typebox/value'

const R = Value.Parse(T, value) // const R: {
// id: string,
// name: string,
// timestamp: number
// }
```

## Types

TypeBox types are Json Schema fragments that compose into more complex types. Each fragment is structured such that any Json Schema compliant validator can runtime assert a value the same way TypeScript will statically assert a type. TypeBox offers a set of Json Types which are used to create Json Schema compliant schematics as well as a JavaScript type set used to create schematics for constructs native to JavaScript.

### Json Types

The following table lists the supported Json types. These types are fully compatible with the Json Schema Draft 7 specification.

```typescript
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
│ TypeBox │ TypeScript │ Json Schema │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Any() │ type T = any │ const T = { } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Unknown() │ type T = unknown │ const T = { } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.String() │ type T = string │ const T = { │
│ │ │ type: 'string' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Number() │ type T = number │ const T = { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Integer() │ type T = number │ const T = { │
│ │ │ type: 'integer' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Boolean() │ type T = boolean │ const T = { │
│ │ │ type: 'boolean' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Null() │ type T = null │ const T = { │
│ │ │ type: 'null' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Literal(42) │ type T = 42 │ const T = { │
│ │ │ const: 42, │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Array( │ type T = number[] │ const T = { │
│ Type.Number() │ │ type: 'array', │
│ ) │ │ items: { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Object({ │ type T = { │ const T = { │
│ x: Type.Number(), │ x: number, │ type: 'object', │
│ y: Type.Number() │ y: number │ required: ['x', 'y'], │
│ }) │ } │ properties: { │
│ │ │ x: { │
│ │ │ type: 'number' │
│ │ │ }, │
│ │ │ y: { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Tuple([ │ type T = [number, number] │ const T = { │
│ Type.Number(), │ │ type: 'array', │
│ Type.Number() │ │ items: [{ │
│ ]) │ │ type: 'number' │
│ │ │ }, { │
│ │ │ type: 'number' │
│ │ │ }], │
│ │ │ additionalItems: false, │
│ │ │ minItems: 2, │
│ │ │ maxItems: 2 │
│ │ │ } │
│ │ │ │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ enum Foo { │ enum Foo { │ const T = { │
│ A, │ A, │ anyOf: [{ │
│ B │ B │ type: 'number', │
│ } │ } │ const: 0 │
│ │ │ }, { │
│ const T = Type.Enum(Foo) │ type T = Foo │ type: 'number', │
│ │ │ const: 1 │
│ │ │ }] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Const({ │ type T = { │ const T = { │
│ x: 1, │ readonly x: 1, │ type: 'object', │
│ y: 2, │ readonly y: 2 │ required: ['x', 'y'], │
│ } as const) │ } │ properties: { │
│ │ │ x: { │
│ │ │ type: 'number', │
│ │ │ const: 1 │
│ │ │ }, │
│ │ │ y: { │
│ │ │ type: 'number', │
│ │ │ const: 2 │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.KeyOf( │ type T = keyof { │ const T = { │
│ Type.Object({ │ x: number, │ anyOf: [{ │
│ x: Type.Number(), │ y: number │ type: 'string', │
│ y: Type.Number() │ } │ const: 'x' │
│ }) │ │ }, { │
│ ) │ │ type: 'string', │
│ │ │ const: 'y' │
│ │ │ }] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Union([ │ type T = string | number │ const T = { │
│ Type.String(), │ │ anyOf: [{ │
│ Type.Number() │ │ type: 'string' │
│ ]) │ │ }, { │
│ │ │ type: 'number' │
│ │ │ }] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Intersect([ │ type T = { │ const T = { │
│ Type.Object({ │ x: number │ allOf: [{ │
│ x: Type.Number() │ } & { │ type: 'object', │
│ }), │ y: number │ required: ['x'], │
│ Type.Object({ │ } │ properties: { │
│ y: Type.Number() │ │ x: { │
│ }) │ │ type: 'number' │
│ ]) │ │ } │
│ │ │ } │
│ │ │ }, { │
│ │ │ type: 'object', |
│ │ │ required: ['y'], │
│ │ │ properties: { │
│ │ │ y: { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ }] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Composite([ │ type T = { │ const T = { │
│ Type.Object({ │ x: number, │ type: 'object', │
│ x: Type.Number() │ y: number │ required: ['x', 'y'], │
│ }), │ } │ properties: { │
│ Type.Object({ │ │ x: { │
│ y: Type.Number() │ │ type: 'number' │
│ }) │ │ }, │
│ ]) │ │ y: { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Never() │ type T = never │ const T = { │
│ │ │ not: {} │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Not( | type T = unknown │ const T = { │
│ Type.String() │ │ not: { │
│ ) │ │ type: 'string' │
│ │ │ } │
│ │ │ } │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Extends( │ type T = │ const T = { │
│ Type.String(), │ string extends number │ const: false, │
│ Type.Number(), │ ? true │ type: 'boolean' │
│ Type.Literal(true), │ : false │ } │
│ Type.Literal(false) │ │ │
│ ) │ │ │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Extract( │ type T = Extract< │ const T = { │
│ Type.Union([ │ string | number, │ type: 'string' │
│ Type.String(), │ string │ } │
│ Type.Number(), │ > │ │
│ ]), │ │ │
│ Type.String() │ │ │
│ ) │ │ │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Exclude( │ type T = Exclude< │ const T = { │
│ Type.Union([ │ string | number, │ type: 'number' │
│ Type.String(), │ string │ } │
│ Type.Number(), │ > │ │
│ ]), │ │ │
│ Type.String() │ │ │
│ ) │ │ │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Mapped( │ type T = { │ const T = { │
│ Type.Union([ │ [_ in 'x' | 'y'] : number │ type: 'object', │
│ Type.Literal('x'), │ } │ required: ['x', 'y'], │
│ Type.Literal('y') │ │ properties: { │
│ ]), │ │ x: { │
│ () => Type.Number() │ │ type: 'number' │
│ ) │ │ }, │
│ │ │ y: { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const U = Type.Union([ │ type U = 'open' | 'close' │ const T = { │
│ Type.Literal('open'), │ │ type: 'string', │
│ Type.Literal('close') │ type T = `on${U}` │ pattern: '^on(open|close)$' │
│ ]) │ │ } │
│ │ │ │
│ const T = Type │ │ │
│ .TemplateLiteral([ │ │ │
│ Type.Literal('on'), │ │ │
│ U │ │ │
│ ]) │ │ │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Record( │ type T = Record< │ const T = { │
│ Type.String(), │ string, │ type: 'object', │
│ Type.Number() │ number │ patternProperties: { │
│ ) │ > │ '^.*$': { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Partial( │ type T = Partial<{ │ const T = { │
│ Type.Object({ │ x: number, │ type: 'object', │
│ x: Type.Number(), │ y: number │ properties: { │
│ y: Type.Number() | }> │ x: { │
│ }) │ │ type: 'number' │
│ ) │ │ }, │
│ │ │ y: { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Required( │ type T = Required<{ │ const T = { │
│ Type.Object({ │ x?: number, │ type: 'object', │
│ x: Type.Optional( │ y?: number │ required: ['x', 'y'], │
│ Type.Number() | }> │ properties: { │
│ ), │ │ x: { │
│ y: Type.Optional( │ │ type: 'number' │
│ Type.Number() │ │ }, │
│ ) │ │ y: { │
│ }) │ │ type: 'number' │
│ ) │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Pick( │ type T = Pick<{ │ const T = { │
│ Type.Object({ │ x: number, │ type: 'object', │
│ x: Type.Number(), │ y: number │ required: ['x'], │
│ y: Type.Number() │ }, 'x'> │ properties: { │
│ }), ['x'] | │ x: { │
│ ) │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Omit( │ type T = Omit<{ │ const T = { │
│ Type.Object({ │ x: number, │ type: 'object', │
│ x: Type.Number(), │ y: number │ required: ['y'], │
│ y: Type.Number() │ }, 'x'> │ properties: { │
│ }), ['x'] | │ y: { │
│ ) │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Index( │ type T = { │ const T = { │
│ Type.Object({ │ x: number, │ type: 'number' │
│ x: Type.Number(), │ y: string │ } │
│ y: Type.String() │ }['x'] │ │
│ }), ['x'] │ │ │
│ ) │ │ │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const A = Type.Tuple([ │ type A = [0, 1] │ const T = { │
│ Type.Literal(0), │ type B = [2, 3] │ type: 'array', │
│ Type.Literal(1) │ type T = [ │ items: [ │
│ ]) │ ...A, │ { const: 0 }, │
│ const B = Type.Tuple([ │ ...B │ { const: 1 }, │
| Type.Literal(2), │ ] │ { const: 2 }, │
| Type.Literal(3) │ │ { const: 3 } │
│ ]) │ │ ], │
│ const T = Type.Tuple([ │ │ additionalItems: false, │
| ...Type.Rest(A), │ │ minItems: 4, │
| ...Type.Rest(B) │ │ maxItems: 4 │
│ ]) │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Uncapitalize( │ type T = Uncapitalize< │ const T = { │
│ Type.Literal('Hello') │ 'Hello' │ type: 'string', │
│ ) │ > │ const: 'hello' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Capitalize( │ type T = Capitalize< │ const T = { │
│ Type.Literal('hello') │ 'hello' │ type: 'string', │
│ ) │ > │ const: 'Hello' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Uppercase( │ type T = Uppercase< │ const T = { │
│ Type.Literal('hello') │ 'hello' │ type: 'string', │
│ ) │ > │ const: 'HELLO' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Lowercase( │ type T = Lowercase< │ const T = { │
│ Type.Literal('HELLO') │ 'HELLO' │ type: 'string', │
│ ) │ > │ const: 'hello' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const R = Type.Ref('T') │ type R = unknown │ const R = { $ref: 'T' } │
│ │ │ │
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
```

### JavaScript Types

TypeBox provides an extended type set that can be used to create schematics for common JavaScript constructs. These types can not be used with any standard Json Schema validator; but can be used to frame schematics for interfaces that may receive Json validated data. JavaScript types are prefixed with the `[JavaScript]` JSDoc comment for convenience. The following table lists the supported types.

```typescript
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
│ TypeBox │ TypeScript │ Extended Schema │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Constructor([ │ type T = new ( │ const T = { │
│ Type.String(), │ arg0: string, │ type: 'Constructor', │
│ Type.Number() │ arg0: number │ parameters: [{ │
│ ], Type.Boolean()) │ ) => boolean │ type: 'string' │
│ │ │ }, { │
│ │ │ type: 'number' │
│ │ │ }], │
│ │ │ returns: { │
│ │ │ type: 'boolean' │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Function([ │ type T = ( │ const T = { │
| Type.String(), │ arg0: string, │ type: 'Function', │
│ Type.Number() │ arg1: number │ parameters: [{ │
│ ], Type.Boolean()) │ ) => boolean │ type: 'string' │
│ │ │ }, { │
│ │ │ type: 'number' │
│ │ │ }], │
│ │ │ returns: { │
│ │ │ type: 'boolean' │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Promise( │ type T = Promise │ const T = { │
│ Type.String() │ │ type: 'Promise', │
│ ) │ │ item: { │
│ │ │ type: 'string' │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = │ type T = │ const T = { │
│ Type.AsyncIterator( │ AsyncIterableIterator< │ type: 'AsyncIterator', │
│ Type.String() │ string │ items: { │
│ ) │ > │ type: 'string' │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Iterator( │ type T = │ const T = { │
│ Type.String() │ IterableIterator │ type: 'Iterator', │
│ ) │ │ items: { │
│ │ │ type: 'string' │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.RegExp(/abc/i) │ type T = string │ const T = { │
│ │ │ type: 'RegExp' │
│ │ │ source: 'abc' │
│ │ │ flags: 'i' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Uint8Array() │ type T = Uint8Array │ const T = { │
│ │ │ type: 'Uint8Array' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Date() │ type T = Date │ const T = { │
│ │ │ type: 'Date' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Undefined() │ type T = undefined │ const T = { │
│ │ │ type: 'undefined' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Symbol() │ type T = symbol │ const T = { │
│ │ │ type: 'symbol' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.BigInt() │ type T = bigint │ const T = { │
│ │ │ type: 'bigint' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Void() │ type T = void │ const T = { │
│ │ │ type: 'void' │
│ │ │ } │
│ │ │ │
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
```

### Options

You can pass Json Schema options on the last argument of any given type. Option hints specific to each type are provided for convenience.

```typescript
// String must be an email
const T = Type.String({ // const T = {
format: 'email' // type: 'string',
}) // format: 'email'
// }

// Number must be a multiple of 2
const T = Type.Number({ // const T = {
multipleOf: 2 // type: 'number',
}) // multipleOf: 2
// }

// Array must have at least 5 integer values
const T = Type.Array(Type.Integer(), { // const T = {
minItems: 5 // type: 'array',
}) // minItems: 5,
// items: {
// type: 'integer'
// }
// }
```

### Properties

Object properties can be modified with Readonly and Optional. The following table shows how these modifiers map between TypeScript and Json Schema.

```typescript
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
│ TypeBox │ TypeScript │ Json Schema │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Object({ │ type T = { │ const T = { │
│ name: Type.ReadonlyOptional( │ readonly name?: string │ type: 'object', │
│ Type.String() │ } │ properties: { │
│ ) │ │ name: { │
│ }) │ │ type: 'string' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Object({ │ type T = { │ const T = { │
│ name: Type.Readonly( │ readonly name: string │ type: 'object', │
│ Type.String() │ } │ properties: { │
│ ) │ │ name: { │
│ }) │ │ type: 'string' │
│ │ │ } │
│ │ │ }, │
│ │ │ required: ['name'] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Object({ │ type T = { │ const T = { │
│ name: Type.Optional( │ name?: string │ type: 'object', │
│ Type.String() │ } │ properties: { │
│ ) │ │ name: { │
│ }) │ │ type: 'string' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
```

### Generic Types

Generic types can be created with generic functions.

```typescript
const Nullable = (T: T) => { // type Nullable = T | null
return Type.Union([T, Type.Null()])
}

const T = Nullable(Type.String()) // type T = Nullable
```

### Recursive Types

Use the Recursive function to create recursive types.

```typescript
const Node = Type.Recursive(This => Type.Object({ // const Node = {
id: Type.String(), // $id: 'Node',
nodes: Type.Array(This) // type: 'object',
}), { $id: 'Node' }) // properties: {
// id: {
// type: 'string'
// },
// nodes: {
// type: 'array',
// items: {
// $ref: 'Node'
// }
// }
// },
// required: [
// 'id',
// 'nodes'
// ]
// }

type Node = Static // type Node = {
// id: string
// nodes: Node[]
// }

function test(node: Node) {
const id = node.nodes[0].nodes[0].id // id is string
}
```

### Module Types

Module types are containers for a set of referential types. Modules act as namespaces, enabling types to reference one another via string identifiers. Modules support both singular and mutually recursive references, as well as deferred dereferencing for computed types such as Partial. Types imported from a module are expressed using the Json Schema `$defs` keyword.

```typescript
const Module = Type.Module({
PartialUser: Type.Partial(Type.Ref('User')), // TComputed<'Partial', [TRef<'User'>]>

User: Type.Object({ // TObject<{
id: Type.String(), // user: TString,
name: Type.String(), // name: TString,
email: Type.String() // email: TString
}), // }>
})
const User = Module.Import('User') // const User: TImport<{...}, 'User'>

type User = Static // type User = {
// id: string,
// name: string,
// email: string
// }

const PartialUser = Module.Import('PartialUser') // const PartialUser: TImport<{...}, 'PartialUser'>

type PartialUser = Static // type PartialUser = {
// id?: string,
// name?: string,
// email?: string
// }
```

### Template Literal Types

TypeBox supports template literal types with the TemplateLiteral function. This type can be created using a syntax similar to the TypeScript template literal syntax or composed from exterior types. TypeBox encodes template literals as regular expressions which enables the template to be checked by Json Schema validators. This type also supports regular expression parsing that enables template patterns to be used for generative types. The following shows both TypeScript and TypeBox usage.

```typescript
// TypeScript

type K = `prop${'A'|'B'|'C'}` // type T = 'propA' | 'propB' | 'propC'

type R = Record // type R = {
// propA: string
// propB: string
// propC: string
// }

// TypeBox

const K = Type.TemplateLiteral('prop${A|B|C}') // const K: TTemplateLiteral<[
// TLiteral<'prop'>,
// TUnion<[
// TLiteral<'A'>,
// TLiteral<'B'>,
// TLiteral<'C'>,
// ]>
// ]>

const R = Type.Record(K, Type.String()) // const R: TObject<{
// propA: TString,
// propB: TString,
// propC: TString,
// }>
```

### Indexed Access Types

TypeBox supports indexed access types with the Index function. This function enables uniform access to interior property and element types without having to extract them from the underlying schema representation. Index types are supported for Object, Array, Tuple, Union and Intersect types.

```typescript
const T = Type.Object({ // type T = {
x: Type.Number(), // x: number,
y: Type.String(), // y: string,
z: Type.Boolean() // z: boolean
}) // }

const A = Type.Index(T, ['x']) // type A = T['x']
//
// ... evaluated as
//
// const A: TNumber

const B = Type.Index(T, ['x', 'y']) // type B = T['x' | 'y']
//
// ... evaluated as
//
// const B: TUnion<[
// TNumber,
// TString,
// ]>

const C = Type.Index(T, Type.KeyOf(T)) // type C = T[keyof T]
//
// ... evaluated as
//
// const C: TUnion<[
// TNumber,
// TString,
// TBoolean
// ]>
```

### Mapped Types

TypeBox supports mapped types with the Mapped function. This function accepts two arguments, the first is a union type typically derived from KeyOf, the second is a mapping function that receives a mapping key `K` that can be used to index properties of a type. The following implements a mapped type that remaps each property to be `T | null`.

```typescript
const T = Type.Object({ // type T = {
x: Type.Number(), // x: number,
y: Type.String(), // y: string,
z: Type.Boolean() // z: boolean
}) // }

const M = Type.Mapped(Type.KeyOf(T), K => { // type M = { [K in keyof T]: T[K] | null }
return Type.Union([Type.Index(T, K), Type.Null()]) //
}) // ... evaluated as
//
// const M: TObject<{
// x: TUnion<[TNumber, TNull]>,
// y: TUnion<[TString, TNull]>,
// z: TUnion<[TBoolean, TNull]>
// }>
```

### Conditional Types

TypeBox supports runtime conditional types with the Extends function. This function performs a structural assignability check against the first (`left`) and second (`right`) arguments and will return either the third (`true`) or fourth (`false`) argument based on the result. The conditional types Exclude and Extract are also supported. The following shows both TypeScript and TypeBox examples of conditional types.

```typescript
// Extends
const A = Type.Extends( // type A = string extends number ? 1 : 2
Type.String(), //
Type.Number(), // ... evaluated as
Type.Literal(1), //
Type.Literal(2) // const A: TLiteral<2>
)

// Extract
const B = Type.Extract( // type B = Extract<1 | 2 | 3, 1>
Type.Union([ //
Type.Literal(1), // ... evaluated as
Type.Literal(2), //
Type.Literal(3) // const B: TLiteral<1>
]),
Type.Literal(1)
)

// Exclude
const C = Type.Exclude( // type C = Exclude<1 | 2 | 3, 1>
Type.Union([ //
Type.Literal(1), // ... evaluated as
Type.Literal(2), //
Type.Literal(3) // const C: TUnion<[
]), // TLiteral<2>,
Type.Literal(1) // TLiteral<3>,
) // ]>
```

### Transform Types

TypeBox supports value decoding and encoding with Transform types. These types work in tandem with the Encode and Decode functions available on the Value and TypeCompiler submodules. Transform types can be used to convert Json encoded values into constructs more natural to JavaScript. The following creates a Transform type to decode numbers into Dates using the Value submodule.

```typescript
import { Value } from '@sinclair/typebox/value'

const T = Type.Transform(Type.Number())
.Decode(value => new Date(value)) // decode: number to Date
.Encode(value => value.getTime()) // encode: Date to number

const D = Value.Decode(T, 0) // const D = Date(1970-01-01T00:00:00.000Z)
const E = Value.Encode(T, D) // const E = 0
```
Use the StaticEncode or StaticDecode types to infer a Transform type.
```typescript
import { Static, StaticDecode, StaticEncode } from '@sinclair/typebox'

const T = Type.Transform(Type.Array(Type.Number(), { uniqueItems: true }))
.Decode(value => new Set(value))
.Encode(value => [...value])

type D = StaticDecode // type D = Set
type E = StaticEncode // type E = Array
type T = Static // type T = Array
```

### Unsafe Types

TypeBox supports user defined types with Unsafe. This type allows you to specify both schema representation and inference type. The following creates an Unsafe type with a number schema that infers as string.

```typescript
const T = Type.Unsafe({ type: 'number' }) // const T = { type: 'number' }

type T = Static // type T = string - ?
```
The Unsafe type is often used to create schematics for extended specifications like OpenAPI.
```typescript

const Nullable = (schema: T) => Type.Unsafe | null>({
...schema, nullable: true
})

const T = Nullable(Type.String()) // const T = {
// type: 'string',
// nullable: true
// }

type T = Static // type T = string | null

const StringEnum = (values: [...T]) => Type.Unsafe({
type: 'string', enum: values
})
const S = StringEnum(['A', 'B', 'C']) // const S = {
// enum: ['A', 'B', 'C']
// }

type S = Static // type S = 'A' | 'B' | 'C'
```

### TypeGuard

TypeBox can check its own types with the TypeGuard module. This module is written for type introspection and provides structural tests for every built-in TypeBox type. Functions of this module return `is` guards which can be used with control flow assertions to obtain schema inference for unknown values. The following guards that the value `T` is TString.

```typescript
import { TypeGuard, Kind } from '@sinclair/typebox'

const T = { [Kind]: 'String', type: 'string' }

if(TypeGuard.IsString(T)) {

// T is TString
}
```

## Values

TypeBox provides an optional Value submodule that can be used to perform structural operations on JavaScript values. This submodule includes functionality to create, check and cast values from types as well as check equality, clone, diff and patch JavaScript values. This submodule is provided via optional import.

```typescript
import { Value } from '@sinclair/typebox/value'
```

### Assert

Use the Assert function to assert a value is valid.

```typescript
let value: unknown = 1

Value.Assert(Type.Number(), value) // throws AssertError if invalid
```

### Create

Use the Create function to create a value from a type. TypeBox will use default values if specified.

```typescript
const T = Type.Object({ x: Type.Number(), y: Type.Number({ default: 42 }) })

const A = Value.Create(T) // const A = { x: 0, y: 42 }
```

### Clone

Use the Clone function to deeply clone a value.

```typescript
const A = Value.Clone({ x: 1, y: 2, z: 3 }) // const A = { x: 1, y: 2, z: 3 }
```

### Check

Use the Check function to type check a value.

```typescript
const T = Type.Object({ x: Type.Number() })

const R = Value.Check(T, { x: 1 }) // const R = true
```

### Convert

Use the Convert function to convert a value into its target type if a reasonable conversion is possible. This function may return an invalid value and should be checked before use. Its return type is `unknown`.

```typescript
const T = Type.Object({ x: Type.Number() })

const R1 = Value.Convert(T, { x: '3.14' }) // const R1 = { x: 3.14 }

const R2 = Value.Convert(T, { x: 'not a number' }) // const R2 = { x: 'not a number' }
```

### Clean

Use Clean to remove excess properties from a value. This function does not check the value and returns an unknown type. You should Check the result before use. Clean is a mutable operation. To avoid mutation, Clone the value first.

```typescript
const T = Type.Object({
x: Type.Number(),
y: Type.Number()
})

const X = Value.Clean(T, null) // const 'X = null

const Y = Value.Clean(T, { x: 1 }) // const 'Y = { x: 1 }

const Z = Value.Clean(T, { x: 1, y: 2, z: 3 }) // const 'Z = { x: 1, y: 2 }
```

### Default

Use Default to generate missing properties on a value using default schema annotations if available. This function does not check the value and returns an unknown type. You should Check the result before use. Default is a mutable operation. To avoid mutation, Clone the value first.

```typescript
const T = Type.Object({
x: Type.Number({ default: 0 }),
y: Type.Number({ default: 0 })
})

const X = Value.Default(T, null) // const 'X = null - non-enumerable

const Y = Value.Default(T, { }) // const 'Y = { x: 0, y: 0 }

const Z = Value.Default(T, { x: 1 }) // const 'Z = { x: 1, y: 0 }
```

### Cast

Use the Cast function to upcast a value into a target type. This function will retain as much information as possible from the original value. The Cast function is intended to be used in data migration scenarios where existing values need to be upgraded to match a modified type.

```typescript
const T = Type.Object({ x: Type.Number(), y: Type.Number() }, { additionalProperties: false })

const X = Value.Cast(T, null) // const X = { x: 0, y: 0 }

const Y = Value.Cast(T, { x: 1 }) // const Y = { x: 1, y: 0 }

const Z = Value.Cast(T, { x: 1, y: 2, z: 3 }) // const Z = { x: 1, y: 2 }
```

### Decode

Use the Decode function to decode a value from a type or throw if the value is invalid. The return value will infer as the decoded type. This function will run Transform codecs if available.

```typescript
const A = Value.Decode(Type.String(), 'hello') // const A = 'hello'

const B = Value.Decode(Type.String(), 42) // throw
```

### Encode

Use the Encode function to encode a value to a type or throw if the value is invalid. The return value will infer as the encoded type. This function will run Transform codecs if available.

```typescript
const A = Value.Encode(Type.String(), 'hello') // const A = 'hello'

const B = Value.Encode(Type.String(), 42) // throw
```

### Parse

Use the Parse function to parse a value. This function calls the `Clone` `Clean`, `Default`, `Convert`, `Assert` and `Decode` Value functions in this exact order to process a value.

```typescript
const R = Value.Parse(Type.String(), 'hello') // const R: string = "hello"

const E = Value.Parse(Type.String(), undefined) // throws AssertError
```

You can override the order in which functions are run, or omit functions entirely using the following.

```typescript
// Runs no functions.

const R = Value.Parse([], Type.String(), 12345)

// Runs the Assert() function.

const E = Value.Parse(['Assert'], Type.String(), 12345)

// Runs the Convert() function followed by the Assert() function.

const S = Value.Parse(['Convert', 'Assert'], Type.String(), 12345)
```

### Equal

Use the Equal function to deeply check for value equality.

```typescript
const R = Value.Equal( // const R = true
{ x: 1, y: 2, z: 3 },
{ x: 1, y: 2, z: 3 }
)
```

### Hash

Use the Hash function to create a [FNV1A-64](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) non-cryptographic hash of a value.

```typescript
const A = Value.Hash({ x: 1, y: 2, z: 3 }) // const A = 2910466848807138541n

const B = Value.Hash({ x: 1, y: 4, z: 3 }) // const B = 1418369778807423581n
```

### Diff

Use the Diff function to generate a sequence of edits that will transform one value into another.

```typescript
const E = Value.Diff( // const E = [
{ x: 1, y: 2, z: 3 }, // { type: 'update', path: '/y', value: 4 },
{ y: 4, z: 5, w: 6 } // { type: 'update', path: '/z', value: 5 },
) // { type: 'insert', path: '/w', value: 6 },
// { type: 'delete', path: '/x' }
// ]
```

### Patch

Use the Patch function to apply a sequence of edits.

```typescript
const A = { x: 1, y: 2 }

const B = { x: 3 }

const E = Value.Diff(A, B) // const E = [
// { type: 'update', path: '/x', value: 3 },
// { type: 'delete', path: '/y' }
// ]

const C = Value.Patch(A, E) // const C = { x: 3 }
```

### Errors

Use the Errors function to enumerate validation errors.

```typescript
const T = Type.Object({ x: Type.Number(), y: Type.Number() })

const R = [...Value.Errors(T, { x: '42' })] // const R = [{
// schema: { type: 'number' },
// path: '/x',
// value: '42',
// message: 'Expected number'
// }, {
// schema: { type: 'number' },
// path: '/y',
// value: undefined,
// message: 'Expected number'
// }]
```

### Mutate

Use the Mutate function to perform a deep mutable value assignment while retaining internal references.

```typescript
const Y = { z: 1 } // const Y = { z: 1 }
const X = { y: Y } // const X = { y: { z: 1 } }
const A = { x: X } // const A = { x: { y: { z: 1 } } }

Value.Mutate(A, { x: { y: { z: 2 } } }) // A' = { x: { y: { z: 2 } } }

const R0 = A.x.y.z === 2 // const R0 = true
const R1 = A.x.y === Y // const R1 = true
const R2 = A.x === X // const R2 = true
```

### Pointer

Use ValuePointer to perform mutable updates on existing values using [RFC6901](https://www.rfc-editor.org/rfc/rfc6901) Json Pointers.

```typescript
import { ValuePointer } from '@sinclair/typebox/value'

const A = { x: 0, y: 0, z: 0 }

ValuePointer.Set(A, '/x', 1) // A' = { x: 1, y: 0, z: 0 }
ValuePointer.Set(A, '/y', 1) // A' = { x: 1, y: 1, z: 0 }
ValuePointer.Set(A, '/z', 1) // A' = { x: 1, y: 1, z: 1 }
```

## Syntax Types

TypeBox provides experimental support for parsing TypeScript annotation syntax into TypeBox types.

This feature is provided via optional import.

```typescript
import { Syntax } from '@sinclair/typebox/syntax'
```

### Create

Use the Syntax function to create TypeBox types from TypeScript syntax ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgChQkWIhTYYwBgWKly1OoxZtO3foMkSGEdDXgAVOAF4Uo3AAoABkhwAuOOgCuIPjygAaOFR3Lx8-AkcASjgY2Jj2djhjUwt3cwB5PgArHgYYAB4ECTiS0rLyisrYhNi3OHMAOW9fAOKq9o7OuBqY4PqmsKg2rpHR+MT8AD4JCS5eeut5LEUGfLmeCCJ6ybHKmvWFmyLdk86euDrQlv9h07uy876rv1v7t-GCIA))

```typescript
const T = Syntax(`{ x: number, y: number }`) // const T: TObject<{
// x: TNumber,
// y: TNumber
// }>

type T = Static // type T = {
// x: number,
// y: number
// }
```

### Parameters

Syntax types can be parameterized to receive exterior types ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgCgJDCOhrwAKnAC8KUbgAUAAyQ4AXHHQBXEHx5QANHFQHjp8wS0BKOK7ev27ODLmKDCgHk+ACseBhgAHgQJd1i4+ITEpLdPN304BQA5EzNLGOSCwqK4VNcbDOz7KHzi2rqPL3wAPikfeRQVNUxNJCV8Ky0ABSxYYCwmCIUm52LUtvhkfyDQ8Kia+o2C0rh0wLAYYFlxycrcpot1zav47fK9g6OJrJzzFuv3m8amoA))

```typescript
const T = Syntax(`{ x: number, y: number }`) // const T: TObject<{
// x: TNumber,
// y: TNumber
// }>

const S = Syntax({ T }, `Partial`) // const S: TObject<{
// x: TOptional,
// y: TOptional
// }>
```

### Generics

Syntax types support generic parameters in the following way ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgChQkWIhTYYwBgWKly1OoxZtO3foMkSGEdDXgA1HgxjQ4AXhSjcACgAGAHgAaAGjgBNXwAtAD45CTg4HAAuOB84cLhUGID4iIAvGMD4-FcASgkjEzM4ACEsOhpLa2gae0dMFyQqmygCX1cEBOi4Zuh3AEZfAAZh4O8EpJ6rFvcRuEG4IbGEjKnqqFnh337lnPyJLl5S8uBK6Zq65AUld0OeCCJjit6oGlCIiPZ2ODun05fag5Oh8QaCweCIZCoV8Pt0kN0FpM5qshm0ElCMZisSCYRFJvCYnNJgsUWjseSKeDcXBVgTFr4kb5Vv0COjKezsTD8EA))

```typescript
const Vector = Syntax(` {
x: X,
y: Y,
z: Z
}`)

const BasisVectors = Syntax({ Vector }, `{
x: Vector<1, 0, 0>,
y: Vector<0, 1, 0>,
z: Vector<0, 0, 1>,
}`)

type BasisVectors = Static // type BasisVectors = {
// x: { x: 1, y: 0, z: 0 },
// y: { x: 0, y: 1, z: 0 },
// z: { x: 0, y: 0, z: 1 }
// }
```

### Options

Options can be passed via the last parameter.

```typescript
const T = Syntax(`number`, { minimum: 42 }) // const T = {
// type: 'number',
// minimum: 42
// }
```

### NoInfer

Syntax parsing is an expensive type level operation and can impact on language service performance. Use the NoInfer function parse syntax at runtime only.

```typescript
import { NoInfer } from '@sinclair/typebox/syntax'

const T = NoInfer(`number | string`) // const T: TSchema = {
// anyOf: [
// { type: 'number' },
// { type: 'string' }
// ]
// }
```

## TypeRegistry

The TypeBox type system can be extended with additional types and formats using the TypeRegistry and FormatRegistry modules. These modules integrate deeply with TypeBox's internal type checking infrastructure and can be used to create application specific types, or register schematics for alternative specifications.

### TypeRegistry

Use the TypeRegistry to register a type. The Kind must match the registered type name.

```typescript
import { TSchema, Kind, TypeRegistry } from '@sinclair/typebox'

TypeRegistry.Set('Foo', (schema, value) => value === 'foo')

const Foo = { [Kind]: 'Foo' } as TSchema

const A = Value.Check(Foo, 'foo') // const A = true

const B = Value.Check(Foo, 'bar') // const B = false
```

### FormatRegistry

Use the FormatRegistry to register a string format.

```typescript
import { FormatRegistry } from '@sinclair/typebox'

FormatRegistry.Set('foo', (value) => value === 'foo')

const T = Type.String({ format: 'foo' })

const A = Value.Check(T, 'foo') // const A = true

const B = Value.Check(T, 'bar') // const B = false
```

## TypeCheck

TypeBox types target Json Schema Draft 7 and are compatible with any validator that supports this specification. TypeBox also provides a built-in type checking compiler designed specifically for TypeBox types that offers high performance compilation and value checking.

The following sections detail using Ajv and the TypeBox compiler infrastructure.