Nit-Picking Magistrate

    @sinclair/typebox
    TypeScript icon, indicating that this package has built-in type declarations

    0.24.27 • Public • Published

    TypeBox

    JSON Schema Type Builder with Static Type Resolution for TypeScript



    npm version Downloads 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 enables one to create unified types that can be statically checked by TypeScript 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.

    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                  parameters: [{               
     ], Type.Boolean())              ) => boolean                     type: 'string'             
                                                                    }, {                         
                                                                      type: 'number'             
                                                                    }],                          
                                                                    return: {                    
                                                                      type: 'boolean'            
                                                                    }                            
                                                                  }                              
                                                                                                 
    ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
     const T = Type.Function([       type T = (                   const T = {                    
    |   Type.String(),                 arg0: string,                 type : 'function',           
       Type.Number()                  arg1: number                  parameters: [{               
     ], Type.Boolean())              ) => boolean                     type: 'string'             
                                                                    }, {                         
                                                                      type: 'number'             
                                                                    }],                          
                                                                    return: {                    
                                                                      type: 'boolean'            
                                                                    }                            
                                                                  }                              
                                                                                                 
    ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
     const T = Type.Uint8Array()     type T = Uint8Array          const T = {                    
                                                                    type: 'object',              
                                                                    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: 'object',              
                                                                    specialized: 'Undefined'     
                                                                  }                              
                                                                                                 
    ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
     const T = Type.Void()           type T = void                const T = {                    
                                                                    type: 'null'                 
                                                                  }                              
                                                                                                 
    └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘

    Reference Types

    Use Type.Ref(...) to create referenced types. 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

    Use Type.Recursive(...) to create recursive types.

    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: Node[]
                                                         // }
    
    function test(node: Node) {
      const id = node.nodes[0].nodes[0]                  // id is string
                     .nodes[0].nodes[0]
                     .id
    }

    Generic Types

    Use functions to create generic types. 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

    Use Type.Unsafe(...) to create custom schemas with user defined inference rules.

    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 to create schemas for validators that require specific schema representations. An example of this would be OpenAPI's nullable and enum schemas which are not provided by TypeBox. The following demonstrates using Type.Unsafe(...) to create these types.

    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
    
    
    //--------------------------------------------------------------------------------------------
    //
    // StringEnum<string[]>
    //
    //--------------------------------------------------------------------------------------------
    
    function StringEnum<T extends string[]>(values: [...T]) {
      return Type.Unsafe<T[number]>({ type: 'string', enum: values })
    }
    
    const T = StringEnum(['A', 'B', 'C'])                // const T = {
                                                         //   enum: ['A', 'B', 'C']
                                                         // }
    
    type T = Static<typeof T>                            // type T = 'A' | 'B' | 'C'

    Conditional Types

    Use the Conditional module to create conditionally mapped types.

    import { Conditional } from '@sinclair/typebox/conditional'

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

    ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
     TypeBox                         TypeScript                   JSON Schema                    
                                                                                                 
    ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
     const T = Conditional.Extends(  type T =                     const T = {                    
       Type.String(),                 string extends number         const: false,                
       Type.Number(),                 true : false                  type: 'boolean'              
       Type.Literal(true),                                        }                              
       Type.Literal(false)                                                                       
     )                                                                                           
                                                                                                 
    ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
     const T = Conditional.Extract(  type T = Extract<            const T = {                    
       Type.Union([                    'a' | 'b' | 'c',             anyOf: [{                    
         Type.Literal('a'),            'a' | 'f'                      const: 'a'                 
         Type.Literal('b'),          >                                type: 'string'             
         Type.Literal('c')                                          }]                           
       ]),                                                        }                              
       Type.Union([                                                                              
         Type.Literal('a'),                                                                      
         Type.Literal('f')                                                                       
       ])                                                                                        
     )                                                                                           
                                                                                                 
    ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
     const T = Conditional.Exclude(  type T = Exclude<            const T = {                    
       Type.Union([                    'a' | 'b' | 'c',             anyOf: [{                    
         Type.Literal('a'),            'a'                            const: 'b',                
         Type.Literal('b'),          >                                type: 'string'             
         Type.Literal('c')                                          }, {                         
       ]),                                                            const: 'c',                
       Type.Union([                                                   type: 'string'             
         Type.Literal('a')                                          }]                           
       ])                                                         }                              
     )                                                                                           
                                                                                                 
    └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘

    Values

    Use the Value module to perform type operations on values.

    import { Value } from '@sinclair/typebox/value'
    
    const T = Type.Object({ x: Type.Number(), y: Type.Number() })
    
    //--------------------------------------------------------------------------------------------
    //
    // Use Value.Create(T) to create a value from T.
    //
    //--------------------------------------------------------------------------------------------
    
    const V = Value.Create(T)                            // const V = { x: 0, y: 0 }
    
    //--------------------------------------------------------------------------------------------
    //
    // Use Value.Check(T, ...) to check if a value is of type T.
    //
    //--------------------------------------------------------------------------------------------
    
    const R = Value.Check(T, { x: 1 })                   // const R = false
    
    //--------------------------------------------------------------------------------------------
    //
    // Use Value.Cast(T, ...) to immutably cast a value into T.
    //
    //--------------------------------------------------------------------------------------------
    
    const A = Value.Cast(T, null)                        // const A = { x: 0, y: 0 }
    
    const B = Value.Cast(T, { x: 1 })                    // const B = { x: 1, y: 0 }
    
    const C = Value.Cast(T, { x: 1, y: 2, z: 3 })        // const C = { x: 1, y: 2 }
    

    Guards

    Use the TypeGuard module to test if values are valid TypeBox types.

    import { TypeGuard } from '@sinclair/typebox/guard'
    
    const T = Type.String()
    
    if(TypeGuard.TString(T)) {
        
      // T is TString
    }

    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 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 T = Type.Object({
      x: Type.Number(),
      y: Type.Number(),
      z: Type.Number()
    })
    
    //--------------------------------------------------------------------------------------------
    //
    // Validate Data
    //
    //--------------------------------------------------------------------------------------------
    
    const R = ajv.validate(T, { x: 1, y: 2, z: 3 })      // const R = true

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

    Compiler

    TypeBox provides an optional high performance runtime compiler and type checker that can be used in applications that require extremely fast validation. This compiler is optimized for TypeBox types whose schematics are known in advance. If defining custom types with Type.Unsafe<T> please consider Ajv.

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

    Use the Compile(...) function to compile a type.

    const C = TypeCompiler.Compile(Type.Object({         // const C: TypeCheck<TObject<{
      x: Type.Number(),                                  //     x: TNumber;
      y: Type.Number(),                                  //     y: TNumber;
      z: Type.Number()                                   //     z: TNumber;
    }))                                                  // }>>
    
    const R = C.Check({ x: 1, y: 2, z: 3 })              // const R = true 

    Validation errors can be read with the Errors(...) function.

    const C = TypeCompiler.Compile(Type.Object({         // const C: TypeCheck<TObject<{
      x: Type.Number(),                                  //     x: TNumber;
      y: Type.Number(),                                  //     y: TNumber;
      z: Type.Number()                                   //     z: TNumber;
    }))                                                  // }>>
    
    const value = { }
    
    const errors = [...C.Errors(value)]                  // const errors = [{
                                                         //   schema: { type: 'number' },
                                                         //   path: '/x',
                                                         //   value: undefined,
                                                         //   message: 'Expected number'
                                                         // }, {
                                                         //   schema: { type: 'number' },
                                                         //   path: '/y',
                                                         //   value: undefined,
                                                         //   message: 'Expected number'
                                                         // }, {
                                                         //   schema: { type: 'number' },
                                                         //   path: '/z',
                                                         //   value: undefined,
                                                         //   message: 'Expected number'
                                                         // }]

    Compiled routines can be inspected with the .Code() function.

    const C = TypeCompiler.Compile(Type.String())        // const C: TypeCheck<TString>
    
    console.log(C.Code())                                // return function check(value) {
                                                         //   return (
                                                         //     (typeof value === 'string')
                                                         //   )
                                                         // }

    Benchmark

    This project maintains a set of benchmarks that measure Ajv and TypeCompiler compilation and validation performance. These benchmarks can be run locally by cloning this repository and running npm run benchmark. The results below show for Ajv version 8.11.0.

    For additional comparative benchmarks, please refer to typescript-runtime-type-benchmarks.

    Compile

    This benchmark measures compilation performance for varying types. You can review this benchmark here.

    ┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┐
         (index)       Iterations      Ajv       TypeCompiler  Performance  
    ├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┤
               Number     2000     '    394 ms'  '      9 ms'  '   43.78 x' 
               String     2000     '    320 ms'  '      9 ms'  '   35.56 x' 
              Boolean     2000     '    326 ms'  '      6 ms'  '   54.33 x' 
                 Null     2000     '    256 ms'  '      6 ms'  '   42.67 x' 
                RegEx     2000     '    494 ms'  '     12 ms'  '   41.17 x' 
              ObjectA     2000     '   2813 ms'  '     41 ms'  '   68.61 x' 
              ObjectB     2000     '   2949 ms'  '     30 ms'  '   98.30 x' 
                Tuple     2000     '   1258 ms'  '     19 ms'  '   66.21 x' 
                Union     2000     '   1308 ms'  '     22 ms'  '   59.45 x' 
              Vector4     2000     '   1589 ms'  '     17 ms'  '   93.47 x' 
              Matrix4     2000     '    932 ms'  '     11 ms'  '   84.73 x' 
       Literal_String     2000     '    343 ms'  '      6 ms'  '   57.17 x' 
       Literal_Number     2000     '    380 ms'  '      6 ms'  '   63.33 x' 
      Literal_Boolean     2000     '    369 ms'  '      4 ms'  '   92.25 x' 
         Array_Number     2000     '    730 ms'  '      6 ms'  '  121.67 x' 
         Array_String     2000     '    764 ms'  '      7 ms'  '  109.14 x' 
        Array_Boolean     2000     '    791 ms'  '      8 ms'  '   98.88 x' 
        Array_ObjectA     2000     '   3550 ms'  '     33 ms'  '  107.58 x' 
        Array_ObjectB     2000     '   3709 ms'  '     33 ms'  '  112.39 x' 
          Array_Tuple     2000     '   2209 ms'  '     15 ms'  '  147.27 x' 
          Array_Union     2000     '   1733 ms'  '     18 ms'  '   96.28 x' 
        Array_Vector4     2000     '   2279 ms'  '     16 ms'  '  142.44 x' 
        Array_Matrix4     2000     '   1587 ms'  '     11 ms'  '  144.27 x' 
    └──────────────────┴────────────┴──────────────┴──────────────┴──────────────┘

    Validate

    This benchmark measures validation performance for varying types. You can review this benchmark here.

    ┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
         (index)       Iterations   ValueCheck       Ajv       TypeCompiler  Performance  
    ├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┼──────────────┤
               Number   1000000    '     27 ms'  '      6 ms'  '      4 ms'  '    1.50 x' 
               String   1000000    '     23 ms'  '     20 ms'  '     11 ms'  '    1.82 x' 
              Boolean   1000000    '     21 ms'  '     19 ms'  '     10 ms'  '    1.90 x' 
                 Null   1000000    '     24 ms'  '     18 ms'  '     10 ms'  '    1.80 x' 
                RegEx   1000000    '    170 ms'  '     43 ms'  '     36 ms'  '    1.19 x' 
              ObjectA   1000000    '    567 ms'  '     34 ms'  '     23 ms'  '    1.48 x' 
              ObjectB   1000000    '    985 ms'  '     50 ms'  '     36 ms'  '    1.39 x' 
                Tuple   1000000    '    119 ms'  '     24 ms'  '     14 ms'  '    1.71 x' 
                Union   1000000    '    302 ms'  '     26 ms'  '     14 ms'  '    1.86 x' 
            Recursive   1000000    '   3071 ms'  '    397 ms'  '    177 ms'  '    2.24 x' 
              Vector4   1000000    '    135 ms'  '     24 ms'  '     11 ms'  '    2.18 x' 
              Matrix4   1000000    '    632 ms'  '     41 ms'  '     30 ms'  '    1.37 x' 
       Literal_String   1000000    '     49 ms'  '     19 ms'  '      9 ms'  '    2.11 x' 
       Literal_Number   1000000    '     56 ms'  '     18 ms'  '      9 ms'  '    2.00 x' 
      Literal_Boolean   1000000    '     56 ms'  '     19 ms'  '      9 ms'  '    2.11 x' 
         Array_Number   1000000    '    408 ms'  '     31 ms'  '     17 ms'  '    1.82 x' 
         Array_String   1000000    '    458 ms'  '     32 ms'  '     20 ms'  '    1.60 x' 
        Array_Boolean   1000000    '    431 ms'  '     34 ms'  '     24 ms'  '    1.42 x' 
        Array_ObjectA   1000000    '  13322 ms'  '   2549 ms'  '   1636 ms'  '    1.56 x' 
        Array_ObjectB   1000000    '  16341 ms'  '   2865 ms'  '   2074 ms'  '    1.38 x' 
          Array_Tuple   1000000    '   1640 ms'  '     92 ms'  '     71 ms'  '    1.30 x' 
          Array_Union   1000000    '   4803 ms'  '    237 ms'  '     89 ms'  '    2.66 x' 
      Array_Recursive   1000000    '  53759 ms'  '   7694 ms'  '   2600 ms'  '    2.96 x' 
        Array_Vector4   1000000    '   2099 ms'  '     96 ms'  '     52 ms'  '    1.85 x' 
        Array_Matrix4   1000000    '  11436 ms'  '    384 ms'  '    310 ms'  '    1.24 x' 
    └──────────────────┴────────────┴──────────────┴──────────────┴──────────────┴──────────────┘

    Compression

    The following table lists esbuild compiled and minified sizes for each TypeBox import.

    ┌──────────────────────┬────────────┬────────────┬─────────────┐
           (index)          Compiled    Minified   Compression 
    ├──────────────────────┼────────────┼────────────┼─────────────┤
     typebox/compiler      '   47 kb'  '   23 kb'   '1.99 x'   
     typebox/conditional   '   41 kb'  '   16 kb'   '2.46 x'   
     typebox/guard         '   20 kb'  '    9 kb'   '2.06 x'   
     typebox/value         '   54 kb'  '   25 kb'   '2.14 x'   
     typebox               '   11 kb'  '    5 kb'   '1.89 x'   
    └──────────────────────┴────────────┴────────────┴─────────────┘

    Contribute

    TypeBox is open to community contribution. Please ensure you submit an open issue before submitting your pull request. The TypeBox project preferences open community discussion prior to accepting new features.

    Install

    npm i @sinclair/typebox

    DownloadsWeekly Downloads

    6,103,672

    Version

    0.24.27

    License

    MIT

    Unpacked Size

    255 kB

    Total Files

    33

    Last publish

    Collaborators

    • sinclair