Skip to content

sinclairzx81/typedriver

Repository files navigation

TypeDriver

A Runtime TypeScript Validation Engine



npm version Downloads License Test

Install

$ npm install typedriver --save

Usage

Compile TypeScript definitions into high performance validators

import compile from 'typedriver'

const Vector = compile(`{
  x: number
  y: number
  z: number
}`)

const value = Vector.parse(data)                    // const value: {
                                                    //   x: number,
                                                    //   y: number,
                                                    //   z: number
                                                    // } = ...

Syntax highlighting is available via the Visual Studio Marketplace

Overview

TypeDriver is a runtime type system that compiles TypeScript, JSON Schema and Standard Schema definitions into high performance JSON Schema validators. It also statically emulates the TypeScript type system inside the TypeScript type system which enables it to infer types from strings.

License MIT

Contents

Compile

TypeScript | JSON Schema | Standard Schema

The compile function will accept any TypeScript, JSON Schema or Standard Schema definition and JIT compile it into a high-performance runtime validator. If the JavaScript environment does not support JIT (i.e. Cloudflare), the compiler will automatically fallback to dynamic validation.

import compile from 'typedriver'

TypeScript

const User = compile(`{
  name: string
}`)

JSON Schema

const User = compile({
  type: 'object',
  required: ['name'],
  properties: {
    name: { 
      type: 'string' 
    }
  }
})

Standard Schema

const User = compile(z.object({
  name: z.string(),
}))

Validate

TypeDriver validators have three validation functions.

Parse

Use parse for check-and-return, otherwise throw

const { x, y, z } = Vector.parse(data)

Check

Use check for fast boolean result

if(Vector.check(data)) {
  const { x, y, z } = data      
}

Errors

Use errors to get diagnostics after a failed check

const errors = Vector.errors(data, {
  format: 'standard-schema',                         // (default) 'json-schema'
  locale: 'ko_KR'                                    // (default) 'en_US'
})
console.log(errors)

Script

Definitions | Options | Generics | Programmable

TypeDriver has advanced type inference support for TypeScript definitions encoded as strings.

Definitions

Type definitions can be specified in the following way.

const Address = `{
  street: string
  city: string
  country: string
}`
const User = `{
  name: string
  email: string
  address: ${Address}
}`
const Product = `{
  id: string
  name: string
  price: number
}`
const Order = `{
  user: ${User}
  products: ${Product}[]
}`

const validator = compile(Order)        // const validator: TValidator<{
                                        //   user: {
                                        //     name: string;
                                        //     email: string;
                                        //     address: {
                                        //       street: string;
                                        //       city: string;
                                        //       country: string;
                                        //     };
                                        //   };
                                        //   products: {
                                        //     name: string;
                                        //     id: string;
                                        //     price: number;
                                        //   }[];
                                        // }>

Options

Data constraints and annotations can be specified via a with keyword. TypeDriver natively understands JSON Schema vocabulary. The following constrains a Vector type.

const Vector = compile(`{
  x: number with { minimum: 0, maximum: 1 },
  y: number with { minimum: 0, maximum: 1 }
} with {
  description: '2D Vector Type'
}`)

console.log(Vector.toJsonSchema())                 // {
                                                   //   type: 'object',
                                                   //   required: [ 'x', 'y' ],
                                                   //   properties: {
                                                   //     x: { 
                                                   //       type: 'number', 
                                                   //       minimum: 0, 
                                                   //       maximum: 1 
                                                   //     },
                                                   //     y: { 
                                                   //       type: 'number', 
                                                   //       minimum: 0,
                                                   //       maximum: 1 
                                                   //     }
                                                   //   },
                                                   //   description: '2D Vector Type'
                                                   // }

Generics

Generic types can be created in the following way

const Generic = <T extends string>(T: T) => `{ 
  x: ${T}, 
  y: ${T} 
}` as const

const TVector = Generic('number')                  // const TVector: `{ 
                                                   //   x: number,
                                                   //   y: number
                                                   // }` = `...`

const Vector = compile(TVector)                    // const Vector: TValidator<{
                                                   //   x: number
                                                   //   y: number
                                                   // }>

Programmable

Programmable mapped and conditional types are supported

import { compile } from 'typedriver'

const Input = `{
  x: number
  y: number
  z: number
}`

const Output = `{
  [K in keyof ${Input}]: ${Input}[K] | null
}`

const validator = compile(Output)                  // const validator: TValidator<{
                                                   //     x: number | null;
                                                   //     y: number | null;
                                                   //     z: number | null;
                                                   // }>

Parse

Transform TypeScript to JSON Schema

Use the parse function to transform TypeScript into JSON Schema.

import { parse, type Static } from 'typedriver'

const Vector = parse(`{
  x: number
  y: number
  z: number
}`)

type Vector = Static<typeof Vector>                // type Vector = {
                                                   //   x: number,
                                                   //   y: number,
                                                   //   z: number
                                                   // }

console.log(Vector)                                // prints: {
                                                   //   type: 'object',
                                                   //   required: ['x', 'y', 'z'],
                                                   //   properties: {
                                                   //     x: { type: 'number'},
                                                   //     y: { type: 'number'},
                                                   //     z: { type: 'number'}
                                                   //   }
                                                   // }

Static

TypeScript | JSON Schema | Standard Schema

TypeDriver has unified type inference for TypeScript, JSON Schema, and Standard Schema. Use the Static<T> type to derive a static TypeScript type from any runtime type definition.

TypeScript

import { type Static } from 'typedriver'

type T = Static<`{ value: number }`>                // type T = {
                                                    //   value: number
                                                    // }

JSON Schema

import { type Static } from 'typedriver'

type T = Static<{                                  // type T = {
  type: 'object',                                  //   value: number
  required: ['value'],                             // }
  properties: {
    value: { 
      type: 'number' 
    }
  }
}>

Standard Schema

import { type Static } from 'typedriver'

const T = z.object({                
  value: z.number() 
})

type T = Static<typeof T>                           // type T = { 
                                                    //   value: number 
                                                    // }

Reflect

TypeDriver uses JSON Schema to represent TypeScript at runtime. Compiled validators include a toJsonSchema() function that returns the internal JSON Schema representation.

import compile from 'typedriver'

const validator = compile(`{ x: number }`)

validator.isJsonSchema()                            // Returns true if the compiled type
                                                    // supports JSON Schema transform. This
                                                    // is true for TypeScript, JSON Schema,
                                                    // and library implementations of 
                                                    // Standard JSON Schema.

validator.toJsonSchema()                            // Returns JSON Schema or an empty 
                                                    // schema {} if not supported.

The original type used for compilation can also be retrieved via:

validator.toType()                                  // Returns the original type or
                                                    // schema used for compilation.

Integrate

Typed Function | Express Router

TypeDriver is designed for framework integration. The following is a starter script for a runtime and static type-safe function that is able to accept any TypeScript, JSON Schema or Standard Schema definition.

import compile, { type Static } from 'typedriver'

// Callback
export type TCallback<
  Input extends unknown, 
  Output extends unknown
> = (value: Input) => Output

// Options
export type TOptions<
  Input extends unknown = unknown, 
  Output extends unknown = unknown
> = {
  input?: Input,
  output?: Output
}

// TypedFunction
export function TypedFunction<const Options extends TOptions,
  Input extends unknown = Static<Options['input']>,
  Output extends unknown = Static<Options['output']>,
  Callback extends TCallback<Input, Output> = TCallback<Input, Output>
>(options: Options, callback: Callback): Callback {
  const input = compile(options['input']) 
  const output = compile(options['output'])
  return (
    (value: unknown) => output.parse(callback(input.parse(value) as never))
  ) as never
}

// Example
const add = TypedFunction({
  input: `{ a: number, b: number }`,
  output: `number`
}, ({ a, b }) => a + b)


const sum = add({ a: 1, b: 2 })                     // const value = 3 

Benchmark

TypeDriver is built for performance and to be as lean as possible while hosting a TypeScript DSL engine and JSON Schema 2020-12 validation compiler. The following are high level metrics for the library.

Performance

The following table shows library throughput with and without TypeDriver acceleration.

$ deno task bench

Performance Metrics

┌────────────┬────────────┬─────────────┬────────────────┬───────────────┬──────────────┐
│ (idx)      │ iterations │ accelerated │ standard (...) │ compile (...) │ performance  │
├────────────┼────────────┼─────────────┼────────────────┼───────────────┼──────────────┤
│ typescript │ 16000000   │ true"     28 ms""     29 ms""    0.97 ×" │
│ jsonschema │ 16000000   │ true"     30 ms""     30 ms""    1.02 ×" │
│ zod        │ 16000000   │ true"    612 ms""     29 ms""   21.10 ×" │
│ arktype    │ 16000000   │ true"    530 ms""     27 ms""   19.32 ×" │
│ valibot    │ 16000000   │ true"   4103 ms""     30 ms""  134.98 ×" │
└────────────┴────────────┴─────────────┴────────────────┴───────────────┴──────────────┘

Last Run: Tue Jun 23 2026

Compression

TypeDriver compresses to approximately 50kb gzipped.

$ deno task metrics

Compression Metrics

┌───────┬─────────────────────────┬─────────────┬─────────────┬────────────┐
│ (idx) │ path                    │ bundled     │ minified    │ gzipped    │
├───────┼─────────────────────────┼─────────────┼─────────────┼────────────┤
│     0 │ "./task/metrics/all.ts""519.58 KB""266.53 KB""51.99 KB" │
└───────┴─────────────────────────┴─────────────┴─────────────┴────────────┘

Contribute

TypeDriver is open to community contribution. Please ensure you submit an issue before submitting a pull request. This project prefers open community discussion before accepting new features.

About

A Runtime TypeScript Validation Engine

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors