$ npm install @sinclair/typemap --save
Parse and Compile Types from TypeScript Syntax (Example)
import { Compile } from '@sinclair/typemap'
const validator = Compile(`{ x: number, y: number }`) // const validator: Validator<TObject<{
// x: TNumber,
// y: TNumber
// }>>
const result = validator.Check({ // as {
x: 1, // x: number,
y: 2 // y: number
}) // }
TypeMap is a syntax frontend and compiler backend for the TypeBox, Valibot and Zod runtime type libraries. It offers a common TypeScript syntax for type construction, a runtime compiler for high-performance validation and type translation from one library to another.
TypeMap is written as an advanced type mapping system for the TypeBox project. It is designed to accelerate remote type libraries on TypeBox infrastructure as well enabling TypeBox to integrate with remote type library infrastructure via reverse type remapping. This project also offers high-performance validation for frameworks that orientate around the Standard Schema TypeScript interface.
License: MIT
- Install
- Usage
- Overview
- Example
- Mapping
- Syntax
- Static
- Json Schema
- Tree Shake
- Compile
- Benchmark
- Contribute
Use TypeScript syntax to create types for TypeBox, Valibot and Zod (Example)
import { TypeBox, Valibot, Zod } from '@sinclair/typemap'
// Syntax Types
const S = `{
x: number,
y: number,
z: number
}`
// Runtime Types
const T = TypeBox(S) // const T: TObject<{ ... }>
const V = Valibot(S) // const V: ObjectSchema<{ ... }, ...>
const Z = Zod(S) // const Z: ZodObject<{ ... }, ...>
Translate TypeBox, Valibot and Zod types (Example)
import { TypeBox, Valibot, Zod } from '@sinclair/typemap'
// Syntax -> Zod -> Valibot -> TypeBox
const T = TypeBox(Valibot(Zod(`{
x: number,
y: number,
z: number
}`)))
Compile Valibot and Zod types on TypeBox infrastructure (Example)
import { Compile } from '@sinclair/typemap'
import z from 'zod'
// Zod Type
const Z = z.object({ // const Z: ZodObject<{
x: z.number(), // x: ZodNumber,
y: z.number(), // y: ZodNumber,
z: z.number(), // z: ZodNumber
}) // }>
// Remap and Compile
const C = Compile(Z) // const C: Validator<TObject<{
// x: TNumber,
// y: TNumber,
// z: TNumber
// }>>
// High Throughout Validation
const R = C.Check({ // Iterations: 10_000_000
x: 1, //
y: 2, // Zod : 4000ms (approx)
z: 3 // TypeMap : 40ms (approx)
})
TypeMap is designed for runtime type translation. It provides one mapping function per library which can be used to translate remote types into types specific to that library. All mapping functions make a best effort attempt to translate the structures and semantics from each library. If no translation is possible, these functions return a never
representation.
Use the Syntax
function to translate types into a Syntax string (Example)
import { Syntax } from '@sinclair/typemap'
const S = Syntax('string[]') // const S: 'string[]' (Syntax)
const T = Syntax(t.Number()) // const T: 'number' (TypeBox)
const V = Syntax(v.string()) // const V: 'string' (Valibot)
const Z = Syntax(z.boolean()) // const Z: 'boolean' (Zod)
Use the TypeBox
function to translate types and syntax into TypeBox types (Example)
import { TypeBox } from '@sinclair/typemap'
const S = TypeBox('string[]') // const S: TArray<TString> (Syntax)
const T = TypeBox(t.Number()) // const T: TNumber (TypeBox)
const V = TypeBox(v.string()) // const V: TString (Valibot)
const Z = TypeBox(z.boolean()) // const Z: TBoolean (Zod)
Use the Valibot
function to translate types and syntax into Valibot types (Example)
import { Valibot } from '@sinclair/typemap'
const S = Valibot('string[]') // const S: v.ArraySchema<...> (Syntax)
const T = Valibot(t.Number()) // const T: v.NumberSchema (TypeBox)
const V = Valibot(v.string()) // const V: v.StringSchema (Valibot)
const Z = Valibot(z.boolean()) // const Z: v.BooleanSchema (Zod)
Use the Zod
function to translate types and syntax into Zod types (Example)
import { Zod } from '@sinclair/typemap'
const S = Zod('string[]') // const S: z.ZodArray<...> (Syntax)
const T = Zod(t.Number()) // const T: z.ZodNumber (TypeBox)
const V = Zod(v.string()) // const V: z.ZodString (Valibot)
const Z = Zod(z.boolean()) // const Z: z.ZodBoolean (Zod)
TypeMap provides an optional TypeScript syntax parser that can be used to construct library types. Syntax parsing is implemented at runtime as well as in the type system. This feature can be used to uniformly construct types across libraries, as well as create types with embedded remote types.
Syntax types can be created by passing a string parameter to any library mapping function. TypeMap supports most TypeScript syntax. If the string contains a syntax error, the function will return a never
type. (Example)
import { TypeBox } from '@sinclair/typemap'
const T = TypeBox('{ x: 1, y: 2 }') // const T: TObject<{
// x: TLiteral<1>,
// y: TLiteral<2>
// }>
const S = TypeBox('!!!') // const S: TNever - Syntax Error
You can pass Json Schema options on the last parameter of a syntax type. TypeMap translates known keywords into appropriate runtime representations if possible (Example)
import { TypeBox, Zod } from '@sinclair/typemap'
const T = TypeBox('string', { // const T: TString = {
format: 'email' // type: 'string',
}) // format: 'email'
// }
const S = Zod('{ x?: number }', { // const S = z.object({
additionalProperties: false // x: z.number().optional()
}) // }).strict()
Syntax types can be parameterized to receive exterior types. Parameters are automatically translated to the receiving type (Example)
import { Valibot, Zod } from '@sinclair/typemap'
const V = Valibot('number') // const V: NumberSchema
// Parameter V mapped for target Z
const Z = Zod({ V }, `{ values: V[] }`) // const Z: ZodObject<{
// values: ZodArray<ZodNumber>
// }, { ... }>
Use parameterized types with functions to create generic syntax types (Example)
import { TypeBox, Valibot, Zod } from '@sinclair/typemap'
// Generic Type
const Vector = <T extends object>(T: T) => TypeBox({ T }, `{
x: T,
y: T,
z: T
}`)
// Instanced Types
const T = Vector(Valibot('number')) // const T: TObject<{
// x: TNumber,
// y: TNumber,
// z: TNumber,
// }>
const S = Vector(Zod('string')) // const S: TObject<{
// x: TString,
// y: TString,
// z: TString,
// }>
Use Static to infer for library and syntax types
import { type Static } from '@sinclair/typemap'
const T = t.Number() // TypeBox
const V = v.string() // Valibot
const Z = z.boolean() // Zod
const S = 'string[]' // Syntax
type S = Static<typeof S> // string[]
type T = Static<typeof T> // number
type V = Static<typeof V> // string
type Z = Static<typeof Z> // boolean
Use TypeBox
to transform remote library types into Json Schema (Example)
import { TypeBox as JsonSchema } from '@sinclair/typemap'
const Z = z.object({ // const Z: z.ZodObject<{
x: z.number(), // x: z.ZodNumber;
y: z.number(), // y: z.ZodNumber;
z: z.number() // z: z.ZodNumber;
}).strict() // }, "strict", ...>
// TypeBox encodes types as Json Schema
const T = JsonSchema(Z) // const T = {
// type: 'object',
// required: ['x', 'y', 'z'],
// additionalProperties: false,
// properties: {
// x: { type: 'number' },
// y: { type: 'number' },
// z: { type: 'number' }
// }
// }
TypeMap takes on TypeBox, Valibot and Zod as peer dependencies. If bundling, it is recommended that you import specific translation functions. By doing this it will by-pass library imports and enable unused libraries to be omitted from the bundle.
import { TypeBoxFromZod } from '@sinclair/typemap' // Use TypeBox & Zod, Tree Shake Valibot
import * as z from 'zod'
const T = TypeBoxFromZod(z.object({ // const T: TObject<{
x: z.number(), // x: TNumber;
y: z.number(), // y: TNumber;
z: z.number() // z: TNumber;
})) // }>
Use the Compile
function to compile TypeBox, Valibot and Zod on TypeBox infrastructure (Example)
import { Compile, Zod } from '@sinclair/typemap'
// Compile Zod Type
const validator = Compile(Zod(`{
x: number,
y: number,
z: number
}`))
const R1 = validator.Check({ x: 1, y: 2, z: 3 }) // Accelerated
// Standard Schema
//
// ... which should have been named 'Standard Validator'
const R2 = validator['~standard'].validate({ x: 1, y: 2, z: 3 })
This project manages a small benchmark that compares validation performance using Zod, Valibot, and TypeBox validators. For more comprehensive community benchmarks, refer to the runtime-type-benchmarks project.
Benchmarks are run for the following type.
type T = { x: number, y: string, z: boolean }
Results show the approximate elapsed time to complete the given iterations
┌─────────┬────────────────┬────────────────────┬────────────┬────────────┐
│ (index) │ library │ using │ iterations │ elapsed │
├─────────┼────────────────┼────────────────────┼────────────┼────────────┤
│ 0 │ 'valibot ' │ 'valibot ' │ 10000000 │ '1534 ms ' │
│ 1 │ 'valibot ' │ 'typebox:value ' │ 10000000 │ '1377 ms ' │
│ 2 │ 'valibot ' │ 'typebox:compile ' │ 10000000 │ '46 ms ' │
└─────────┴────────────────┴────────────────────┴────────────┴────────────┘
┌─────────┬────────────────┬────────────────────┬────────────┬────────────┐
│ (index) │ library │ using │ iterations │ elapsed │
├─────────┼────────────────┼────────────────────┼────────────┼────────────┤
│ 0 │ 'zod ' │ 'zod ' │ 10000000 │ '4669 ms ' │
│ 1 │ 'zod ' │ 'typebox:value ' │ 10000000 │ '1359 ms ' │
│ 2 │ 'zod ' │ 'typebox:compile ' │ 10000000 │ '47 ms ' │
└─────────┴────────────────┴────────────────────┴────────────┴────────────┘
This project is open to community contributions. Please ensure you submit an open issue before creating a pull request. TypeBox and associated projects preference open community discussion before accepting new features.