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'

Example

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 inferred as TypeScript types. The schemas produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox allows one to compose unified types that can be statically asserted by the TypeScript compiler as well as 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. It can be used in both TypeScript and JavaScript environments.

License MIT

Contents

Usage

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,                β”‚   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                 β”‚   type: 'object',              β”‚
β”‚     x: Type.Number()           β”‚ } & {                       β”‚   properties: {                β”‚
β”‚   }),                          β”‚   y: number                 β”‚     x: {                       β”‚
β”‚   Type.Object({                β”‚ }                           β”‚       type: 'number'           β”‚
β”‚     y: Type.Number()           β”‚                             β”‚     },                         β”‚
β”‚   })                           β”‚                             β”‚     y: {                       β”‚
β”‚ ])                             β”‚                             β”‚       type: 'number'           β”‚
β”‚                                β”‚                             β”‚     }                          β”‚
β”‚                                β”‚                             β”‚   },                           β”‚
β”‚                                β”‚                             β”‚   required: ['x', 'y']         β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚                                β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 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                β”‚   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 options 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 })

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.Uint8Array()    β”‚ type T = Uint8Array         β”‚ const T = {                    β”‚
β”‚                                β”‚                             β”‚   type: 'Uint8Array',          β”‚
β”‚                                β”‚                             β”‚   specialized: 'Uint8Array'    β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚                                β”‚                             β”‚                                β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 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: 'null'                 β”‚
β”‚                                β”‚                             β”‚ }                              β”‚
β”‚                                β”‚                             β”‚                                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Reference Types

Types can be referenced with Type.Ref(...). To reference a type, the target type must specify an $id.

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

Recursive Types

Recursive types can be created with the Type.Recursive(...) function.

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

type Node = Static<typeof Node>                      // type Node = {
                                                     //   id: string
                                                     //   nodes: ...
                                                     // }

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

Generic Types

Generic types can be created using functions. The following creates a generic Nullable<T> type.

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

const Nullable = <T extends TSchema>(type: T) => Type.Union([type, 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

Unsafe Types

In some cases, you may need schema definitions that are not provided by TypeBox. In these scenarios, it’s common to want to define your own schema and static type inference rules. The Type.Unsafe(...) function provides this functionality, allowing you to specify both schema representation and a static type to infer. Consider the following which defines a number schema, but will infer as a string.

const T = Type.Unsafe<string>({ type: 'number' })    // const T = {
                                                     //   type: 'number'
                                                     // }

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

The Type.Unsafe(...) function can be used with function generics to create custom schema representations for validators requiring specific schema representations. An example of which would be OpenAPI’s nullable and string-enum representations which are not provided by TypeBox by default. The following demonstrates creating these schemas using the Type.Unsafe(...) function.

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

//--------------------------------------------------------------------------------------------
//
// Nullable<T>
//
//--------------------------------------------------------------------------------------------

function Nullable<T extends TSchema>(schema: T) {
  return Type.Unsafe<Static<T> | null>({ ...schema, nullable: true })
}

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

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

//--------------------------------------------------------------------------------------------
//
// StringUnion<[...]>
//
//--------------------------------------------------------------------------------------------

function StringEnum<T extends string[]>(values: [...T]) {
  return Type.Unsafe<T[number]>({ enum: values })
}

const T = StringEnum(['A', 'B', 'C'])                // const T = {
                                                     //   enum: ['A', 'B', 'C']
                                                     // }

type T = Static<typeof T>                            // type T = 'A' | 'B' | 'C'

Values

TypeBox can construct default values for types. TypeBox will create reasonable defaults for any given type, or produce values based on the schemas the default value if specified.

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

const T = Type.Object({
  x: Type.Number({ default: 1 }),
  y: Type.Number({ default: 2 }),
  z: Type.Number()
})

const V = Value.Create(T)                            // const V = {
                                                     //   x: 1,
                                                     //   y: 2,
                                                     //   z: 0
                                                     // }

Strict

TypeBox schemas contain the Kind and Modifier symbol properties. These properties are provided to enable runtime type reflection on schemas, as well as helping TypeBox internally compose types. 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 necessary.

const T = Type.Object({                              // const T = {
  name: Type.Optional(Type.String())                 //   [Kind]: 'Object',
})                                                   //   type: 'object',
                                                     //   properties: {
                                                     //     name: {
                                                     //       [Kind]: 'String',
                                                     //       type: 'string',
                                                     //       [Modifier]: 'Optional'
                                                     //     }
                                                     //   }
                                                     // }

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

Validation

TypeBox schemas target JSON Schema draft 6 so any validator capable of draft 6 should be fine. A good library to use for validation in JavaScript environments is AJV. The following example shows setting up AJV 7 to work with TypeBox.

$ npm install ajv ajv-formats --save
//--------------------------------------------------------------------------------------------
//
// Import TypeBox and AJV
//
//--------------------------------------------------------------------------------------------

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

//--------------------------------------------------------------------------------------------
//
// 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'
])

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

const Vector = Type.Object({
  x: Type.Number(),
  y: Type.Number(),
  z: Type.Number(),
}, { additionalProperties: false })

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

const OK = ajv.validate(Vector, { 
  x: 1,
  y: 2,
  z: 3
}) // -> true

Please refer to the official AJV documentation for additional information on using AJV.

Compiler

TypeBox provides an optional type compiler that can be used as a runtime type checker in absense of a JSON Schema validator. Please note that this compiler is not fully JSON Schema compliant and only permits compilation of TypeBox types only (where the schema representation is known in advance). The TypeCompiler contains a TypeCompiler.Compile(T) method that returns a TypeCheck<T> object that can be used to test the validity of a value.

import { TypeCompiler } from '@sinclair/typebox/compiler'
import { Type } from '@sinclair/typebox'

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

const C = TypeCompiler.Compile(T)

const OK = C.Check({ 
  x: 1, 
  y: 2, 
  z: 3 
}) // -> true

Contribute

TypeBox is open to community contribution, however please ensure you submit an open issue before submitting your pull request. The TypeBox project does preference open community discussion prior to accepting new features.