Skip to main content
Deno 2 is finally here πŸŽ‰οΈ
Learn more

TypeBox

JSON Schema Type Builder with Static Type Resolution for TypeScript

npm version GitHub CI

Install

Node

$ npm install @sinclair/typebox --save

Deno

import { Static, Type } from 'https://deno.land/x/typebox/src/typebox.ts'

Usage

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

const T = Type.String()     // const T = { "type": "string" }

type T = Static<typeof T>   // type T = string

Overview

TypeBox is a type builder library that creates in-memory JSON Schema objects that can be statically resolved to TypeScript types. The schemas produced by this library are built to match the static type checking rules of the TypeScript compiler. TypeBox allows one to create a single unified type that can be both statically checked by the TypeScript compiler and runtime asserted using standard JSON schema validation.

TypeBox can be used as a simple tool to build up complex schemas or integrated into RPC or REST services to help validate JSON data received over the wire. TypeBox does not provide any JSON schema validation. Please use libraries such as AJV to validate schemas built with this library.

Requires TypeScript 4.3.5 and above.

License MIT

Contents

Example

The following demonstrates TypeBox’s general usage.

import { Static, Type } 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<typeof T>           // type T = {
                                    //    id: string,
                                    //    name: string,
                                    //    timestamp: number
                                    // }

//--------------------------------------------------------------------------------------------
//
// ... then use the type both as JSON schema and as a TypeScript type.
//
//--------------------------------------------------------------------------------------------

function receive(value: T) {      // ... as a Type

    if(JSON.validate(T, value)) { // ... as a Schema

        // ok...
    }
}

Types

The following table outlines the TypeBox mappings between TypeScript and JSON schema.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 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.RegEx(/foo/)	 β”‚ type T = string             β”‚ const T = {                    β”‚
β”‚                                β”‚                             β”‚    type: 'string',             β”‚
β”‚                                β”‚                             β”‚    pattern: 'foo'              β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 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                β”‚   properties: {                β”‚
β”‚ })                             β”‚ }                           β”‚      x: {                      β”‚
β”‚                                β”‚                             β”‚        type: 'number'          β”‚
β”‚   	                         β”‚                             β”‚      },                        β”‚
β”‚   	                         β”‚                             β”‚      y: {                      β”‚
β”‚   	                         β”‚                             β”‚        type: 'number'          β”‚
β”‚                                β”‚                             β”‚      }                         β”‚
β”‚   	                         β”‚                             β”‚   },                           β”‚
β”‚   	                         β”‚                             β”‚   required: ['x', 'y']         β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 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.KeyOf(          β”‚ type T = keyof {            β”‚ const T = {                    β”‚
β”‚   Type.Object({                β”‚   x: number,                β”‚    enum: ['x', 'y'],           β”‚
β”‚     x: Type.Number(),          β”‚   y: number                 β”‚    type: 'string'              β”‚
β”‚     y: Type.Number()           β”‚ }                           β”‚ }                              β”‚
β”‚   })                           β”‚                             β”‚                                β”‚
β”‚ )                              β”‚                             β”‚                                β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 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                β”‚       properties: {            β”‚
β”‚    Type.Object({               β”‚ }                           β”‚          a: {                  β”‚
β”‚       y: Type.Number()         β”‚                             β”‚            type: 'number'      β”‚    
β”‚   })                           β”‚                             β”‚          }                     β”‚
β”‚ })                             β”‚                             β”‚       },                       β”‚
β”‚                                β”‚                             β”‚       required: ['a']          β”‚
β”‚                                β”‚                             β”‚    }, {                        β”‚
β”‚                                β”‚                             β”‚       type: 'object',          β”‚
β”‚                                β”‚                             β”‚       properties: {            β”‚
β”‚                                β”‚                             β”‚          b: {                  β”‚
β”‚   	                         β”‚                             β”‚            type: 'number'      β”‚
β”‚   	                         β”‚                             β”‚          }                     β”‚
β”‚   	                         β”‚                             β”‚       },                       β”‚
β”‚   	                         β”‚                             β”‚       required: ['b']          β”‚
β”‚   	                         β”‚                             β”‚    }]                          β”‚
β”‚   	                         β”‚                             β”‚ }                              β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ const T = Type.Record(         β”‚ type T = {                  β”‚ const T = {                    β”‚
β”‚    Type.String(),              β”‚    [key: string]: number    β”‚    type: 'object',             β”‚
β”‚    Type.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               β”‚   properties: {                β”‚
β”‚          Type.Number()         | }>                          β”‚     x: {                       β”‚
β”‚       ),                       β”‚                             β”‚        type: 'number'          β”‚
β”‚       y: Type.Optional(        β”‚                             β”‚     },                         β”‚
β”‚          Type.Number()         β”‚                             β”‚     y: {                       β”‚
β”‚       )                        β”‚                             β”‚        type: 'number'          β”‚
β”‚    })                          β”‚                             β”‚     }                          β”‚
β”‚ )                              β”‚                             β”‚   }                            β”‚
β”‚                                β”‚                             β”‚   required: ['x', 'y']         β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ const T = Type.Pick(           β”‚ type T = Pick<{             β”‚ const T = {                    β”‚
β”‚    Type.Object({               β”‚    x: number,               β”‚   type: 'object',              β”‚
β”‚       x: Type.Number(),        β”‚    y: number                β”‚   properties: {                β”‚
β”‚       y: Type.Number(),        | }, 'x'>                     β”‚     x: {                       β”‚
β”‚     }), ['x']                  β”‚                             β”‚        type: 'number'          β”‚
β”‚ )                              β”‚                             β”‚     }                          β”‚
β”‚                                β”‚                             β”‚   },                           β”‚
β”‚                                β”‚                             β”‚   required: ['x']              β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚                                β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ const T = Type.Omit(           β”‚ type T = Omit<{             β”‚ const T = {                    β”‚
β”‚    Type.Object({               β”‚    x: number,               β”‚   type: 'object',              β”‚
β”‚       x: Type.Number(),        β”‚    y: number                β”‚   properties: {                β”‚
β”‚       y: Type.Number(),        | }, 'x'>                     β”‚     y: {                       β”‚
β”‚     }), ['x']                  β”‚                             β”‚        type: 'number'          β”‚
β”‚ )                              β”‚                             β”‚     }                          β”‚
β”‚                                β”‚                             β”‚   },                           β”‚
β”‚                                β”‚                             β”‚   required: ['y']              β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚                                β”‚                             β”‚                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Modifiers

TypeBox provides modifiers that can be applied to an objects properties. This allows for optional and readonly to be applied to that property. The following table illustates how they map between TypeScript and JSON Schema.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ TypeBox                        β”‚ TypeScript                  β”‚ JSON Schema                    β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ const T = Type.Object({        β”‚ type T = {                  β”‚ const T = {                    β”‚
β”‚   name: Type.Optional(         β”‚    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.ReadonlyOptional( β”‚    readonly name?: string,  β”‚   type: 'object',              β”‚
β”‚      Type.String(),            β”‚ }                           β”‚   properties: {                β”‚
β”‚   )	                         β”‚                             β”‚      name: {                   β”‚
β”‚ })  	                         β”‚                             β”‚        type: 'string'          β”‚
β”‚   	                         β”‚                             β”‚      }                         β”‚
β”‚   	                         β”‚                             β”‚   }                            β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Options

You can pass additional JSON schema properties on the last argument of any given type. The following are some examples.

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

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

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

Generic Types

TypeBox supports Generic Types. The following creates a Generic Type Nullable<T>.

import { Type, Static, TSchema } from '@sinclair/typebox'

function Nullable<T extends TSchema>(t: T) {

    return Type.Union([t, Type.Null()])
}

const T = Nullable(Type.String())            // const T = {
                                             //   "anyOf": [{
                                             //      type: 'string'
                                             //   }, {
                                             //      type: 'null'
                                             //   }]
                                             // }

type T = Static<typeof T>                    // type T = string | null

const U = Nullable(Type.Number())            // const U = {
                                             //   "anyOf": [{
                                             //      type: 'number'
                                             //   }, {
                                             //      type: 'null'
                                             //   }]
                                             // }

type U = Static<typeof U>                    // type U = number | null

Reference Types

Reference Types can be used to reduce schema duplication. TypeBox provides support for referencing with the Type.Ref(...) and Type.Box(...) functions. The Type.Ref(...) function references into an existing type and Type.Box(...) provides a container for multiple referenceable types. To reference a type you must specify an $id on the target type being referenced. The following example shows referencing an existing string type.

const T = Type.String({ $id: 'T' })          // const T = {
                                             //    $id: 'T',
                                             //    type: 'string'
                                             // }
                                             
const R = Type.Ref(T)                        // const R = {
                                             //    $ref: 'T'
                                             // }

The Type.Box(...) function provides a way to group related types under a common namespace. The following example groups a set of related Vector types under the namespace Math3D which are later referenced in the Vertex structure below.

const Math3D = Type.Box({                     //  const Math3D = {
  Vector4: Type.Object({                      //    $id: 'Math3D',
    x: Type.Number(),                         //    definitions: {
    y: Type.Number(),                         //      Vector4: {
    z: Type.Number(),                         //        type: 'object',
    w: Type.Number()                          //        properties: {
  }),                                         //          x: { type: 'number' },
  Vector3: Type.Object({                      //          y: { type: 'number' },
    x: Type.Number(),                         //          z: { type: 'number' },
    y: Type.Number(),                         //          w: { type: 'number' }
    z: Type.Number()                          //        },
  }),                                         //        required: ['x', 'y', 'z', 'w']
  Vector2: Type.Object({                      //      },
    x: Type.Number(),                         //      Vector3: {
    y: Type.Number()                          //        type: 'object',
  })                                          //        properties: {
}, { $id: 'Math3D' })                         //          x: { 'type': 'number' },
                                              //          y: { 'type': 'number' },
                                              //          z: { 'type': 'number' }
                                              //        },
                                              //        required: ['x', 'y', 'z']
                                              //      },
                                              //      Vector2: {
                                              //        type: 'object',
                                              //        properties: {
                                              //          x: { 'type': 'number' },
                                              //          y: { 'type': 'number' },
                                              //        },
                                              //        required: ['x', 'y']
                                              //      }
                                              //    }
                                              //  }
                                                     
const Vertex = Type.Object({                  //  const Vertex = {
    position: Type.Ref(Math3D, 'Vector4'),    //    type: 'object',
    normal:   Type.Ref(Math3D, 'Vector3'),    //    properties: {
    uv:       Type.Ref(Math3D, 'Vector2')     //      position: { $ref: 'Math3D#/definitions/Vector4' },
})                                            //      normal: { $ref: 'Math3D#/definitions/Vector3' },
                                              //      uv: { $ref: 'Math3D#/definitions/Vector2' }
                                              //    },
                                              //    required: ['position', 'normal', 'uv']
                                              //  }

Recursive Types

TypeBox provides support for creating recursive schemas. This is handled with the Type.Rec(...) function. The following will create a Node type that contains an array of inner Nodes. Note that due to current restrictions on TypeScript recursive inference, it’s currently not possible for TypeBox to statically infer for recursive types. Instead TypeBox will resolve inner recursive types as any.

const Node = Type.Rec(Self => Type.Object({   // const Node = {
  id:    Type.String(),                       //   $id: 'Node',
  nodes: Type.Array(Self),                    //   $ref: 'Node#/definitions/self',
}), { $id: 'Node' })                          //   definitions: {
                                              //     self: {
                                              //       type: 'object',
                                              //       properties: {
                                              //         id: {
                                              //           type: 'string'
                                              //         },
                                              //         nodes: {
                                              //            type: 'array',
                                              //            items: {
                                              //              $ref: 'Node#/definitions/self'
                                              //            }
                                              //         }
                                              //      }
                                              //    }
                                              // }

type Node = Static<typeof Node>               // type Node = {
                                              //   id: string
                                              //   nodes: any[]
                                              //

function visit(node: Node) {
    for(const inner of node.nodes) {
        visit(inner as Node)                   // Assert inner as Node
    }
}

Extended Types

In addition to JSON schema types, TypeBox provides several extended types that allow for function and constructor types to be composed. These additional types are not valid JSON Schema and will not validate using typical JSON Schema validation. However, these types can be used to frame JSON schema and describe callable interfaces that may receive JSON validated data. These types are as follows.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ TypeBox                        β”‚ TypeScript                  β”‚ Extended Schema                β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ const T = Type.Constructor([   β”‚ type T = new (              β”‚ const T = {                    β”‚
β”‚    Type.String(),              β”‚  arg0: string,              β”‚   type: 'constructor'          β”‚
β”‚    Type.Number(),              β”‚  arg1: number               β”‚   arguments: [{                β”‚
β”‚ ], 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               β”‚   arguments: [{                β”‚
β”‚ ], Type.Boolean())             β”‚ ) => boolean                β”‚      type: 'string'            β”‚
β”‚                                β”‚                             β”‚   }, {                         β”‚
β”‚                                β”‚                             β”‚      type: 'number'            β”‚
β”‚                                β”‚                             β”‚   }],                          β”‚
β”‚                                β”‚                             β”‚   returns: {                   β”‚
β”‚                                β”‚                             β”‚      type: 'boolean'           β”‚
β”‚                                β”‚                             β”‚   }                            β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ const T = Type.Promise(        β”‚ type T = Promise<string>    β”‚ const T = {                    β”‚
β”‚    Type.String()               β”‚                             β”‚   type: 'promise',             β”‚
β”‚ )                              β”‚                             β”‚   item: {                      β”‚
β”‚                                β”‚                             β”‚      type: 'string'            β”‚
β”‚                                β”‚                             β”‚   }                            β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ const T = Type.Undefined()     β”‚ type T = undefined          β”‚ const T = {                    β”‚
β”‚                                β”‚                             β”‚   type: 'undefined'            β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ const T = Type.Void()          β”‚ type T = void               β”‚ const T = {                    β”‚
β”‚                                β”‚                             β”‚   type: 'void'                 β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚   	                         β”‚                             β”‚                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Strict

TypeBox includes the properties kind and modifier on each underlying schema. These properties are used to help TypeBox statically resolve the schemas to the appropriate TypeScript type as well as apply the appropriate modifiers to an objects properties (such as optional). These properties are not strictly valid JSON schema so in some cases it may be desirable to omit them. TypeBox provides a Type.Strict() function that will omit these properties if nessasary.

const T = Type.Object({                       // const T = {
    name: Type.Optional(Type.String())        //   kind: Symbol(ObjectKind),
})                                            //   type: 'object',
                                              //   properties: {
                                              //     name: {
                                              //       kind: Symbol(StringKind),
                                              //       type: 'string',
                                              //       modifier: Symbol(OptionalModifier)
                                              //     }
                                              //   }
                                              // }

const U = Type.Strict(T)                      // const U = {
                                              //     type: 'object', 
                                              //     properties: { 
                                              //         name: { 
                                              //             type: 'string' 
                                              //         } 
                                              //     } 
                                              // }

Validation

TypeBox does not provide JSON schema validation out of the box and expects users to select an appropriate JSON schema validation library for their needs. TypeBox schemas should match JSON Schema draft 2019-09 so any library capable of draft 2019-09 should be fine. A good library to use for validation is Ajv. The following example shows setting up Ajv 7 to work with TypeBox.

$ npm install ajv ajv-formats --save
//--------------------------------------------------------------------------------------------
//
// Import the 2019 compliant validator from AJV
//
//--------------------------------------------------------------------------------------------

import { Type }   from '@sinclair/typebox'
import addFormats from 'ajv-formats'
import Ajv        from 'ajv/dist/2019'

//--------------------------------------------------------------------------------------------
//
// Setup AJV validator with the following options and formats
//
//--------------------------------------------------------------------------------------------

const ajv = addFormats(new Ajv({}), [
    'date-time', 
    'time', 
    'date', 
    'email',  
    'hostname', 
    'ipv4', 
    'ipv6', 
    'uri', 
    'uri-reference', 
    'uuid',
    'uri-template', 
    'json-pointer', 
    'relative-json-pointer', 
    'regex'
]).addKeyword('kind')
  .addKeyword('modifier')

//--------------------------------------------------------------------------------------------
//
// Create a TypeBox type
//
//--------------------------------------------------------------------------------------------

const User = Type.Object({
    id:     Type.String({ format: 'uuid' }),
    email:  Type.String({ format: 'email' }),
    online: Type.Boolean(),
}, { additionalProperties: false })

//--------------------------------------------------------------------------------------------
//
// Validate Data
//
//--------------------------------------------------------------------------------------------

const ok = ajv.validate(User, { 
    id:    '68b4b1d8-0db6-468d-b551-02069a692044', 
    email: 'dave@domain.com',
    online: true
}) // -> ok

Reference Types

Reference Types can be added to AJV with the ajv.addSchema(...) function. The following moves the id and email types above into a common box and registers it with the validator.

//--------------------------------------------------------------------------------------------
//
// Common Types
//
//--------------------------------------------------------------------------------------------

const Common = Type.Box({
  UserId: Type.String({ format: 'uuid' }),
  Email:  Type.String({ format: 'email' })
}, { $id: 'Common' })

//--------------------------------------------------------------------------------------------
//
// Setup AJV validator with the following options and formats
//
//--------------------------------------------------------------------------------------------

const ajv = addFormats(new Ajv({}), [...])
  .addKeyword('kind')
  .addKeyword('modifier')
  .addSchema(Common) // <-- Register Common Types

//--------------------------------------------------------------------------------------------
//
// Create a TypeBox type
//
//--------------------------------------------------------------------------------------------

const User = Type.Object({
  id:     Type.Ref(Common, 'UserId'),
  email:  Type.Ref(Common, 'Email'),
  online: Type.Boolean()
}, { additionalProperties: false })

//--------------------------------------------------------------------------------------------
//
// Validate Data
//
//--------------------------------------------------------------------------------------------

const ok = ajv.validate(User, { 
    id:    '68b4b1d8-0db6-468d-b551-02069a692044', 
    email: 'dave@domain.com',
    online: true
}) // -> ok

For more information on AJV, refer to the website located here.