CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sinclair--typebox

Json Schema Type Builder with Static Type Resolution for TypeScript

Pending
Overview
Eval results
Files

compilation.mddocs/

Compilation

High-performance validation through schema compilation to optimized JavaScript code. The TypeCompiler generates fast validation functions that significantly outperform standard JSON Schema validators.

Capabilities

Schema Compilation

Compile Function

Compiles a schema to an optimized runtime checker.

/**
 * Compiles schema to optimized runtime checker
 * @param schema - Schema to compile
 * @returns TypeCheck instance with validation methods
 */
function Compile<T extends TSchema>(schema: T, references?: TSchema[]): TypeCheck<T>;

interface TypeCheck<T extends TSchema> {
  /** Check if value matches schema */
  Check(value: unknown): value is Static<T>;
  /** Get validation errors for value */
  Errors(value: unknown): ValueErrorIterator;
  /** Get source code of compiled checker */
  Code(): string;
  /** Decode transformed values (for transform schemas) */
  Decode(value: unknown): StaticDecode<T>;
  /** Encode values for transformation (for transform schemas) */
  Encode(value: unknown): StaticEncode<T>;
}

Usage Examples:

import { TypeCompiler, Type } from "@sinclair/typebox";

const User = Type.Object({
  name: Type.String({ minLength: 2 }),
  age: Type.Number({ minimum: 0, maximum: 120 }),
  email: Type.String({ format: 'email' }),
  isActive: Type.Optional(Type.Boolean())
});

// Compile the schema
const userChecker = TypeCompiler.Compile(User);

// Use compiled checker for validation
const userData = { name: "Alice", age: 25, email: "alice@example.com" };

if (userChecker.Check(userData)) {
  console.log("Valid user:", userData);
  // TypeScript knows userData is properly typed here
} else {
  console.log("Invalid user");
  for (const error of userChecker.Errors(userData)) {
    console.log(`${error.path}: ${error.message}`);
  }
}

Code Generation

Generates validation code as a string for inspection or advanced use cases.

/**
 * Generates validation code as string
 * @param schema - Schema to generate code for
 * @param options - Code generation options
 * @returns Generated JavaScript code
 */
function Code<T extends TSchema>(schema: T, references?: TSchema[], options?: TypeCompilerCodegenOptions): string;

interface TypeCompilerCodegenOptions {
  /** Function name for generated code (default: 'check') */
  functionName?: string;
  /** Include source maps in generated code */
  sourceMaps?: boolean;
  /** Optimize for size vs speed */
  optimize?: 'size' | 'speed';
}

Usage Examples:

const User = Type.Object({
  name: Type.String(),
  age: Type.Number()
});

// Generate code with default options
const defaultCode = TypeCompiler.Code(User);
console.log(defaultCode);

// Generate code with custom function name
const namedCode = TypeCompiler.Code(User, { 
  functionName: 'validateUser' 
});

// Generated code can be used in dynamic contexts
const validateFn = new Function('return ' + namedCode)();
const isValid = validateFn({ name: "Alice", age: 25 });

Performance Characteristics

The compiled validators provide significant performance benefits:

  • 10-100x faster than standard JSON Schema validators
  • Type-specific optimizations for each schema type
  • Minimal memory allocation during validation
  • Branch optimization for union and conditional types
  • Inline validation without function call overhead

Performance Example:

import { TypeCompiler, Value, Type } from "@sinclair/typebox";

const schema = Type.Object({
  users: Type.Array(Type.Object({
    id: Type.String(),
    name: Type.String(),
    email: Type.String({ format: 'email' }),
    age: Type.Number({ minimum: 0, maximum: 120 })
  }))
});

const compiledChecker = TypeCompiler.Compile(schema);
const largeDataset = /* ... thousands of user objects ... */;

// Compiled validation (fast)
console.time('Compiled');
for (const item of largeDataset) {
  compiledChecker.Check(item);
}
console.timeEnd('Compiled');

// Standard validation (slower)  
console.time('Standard');
for (const item of largeDataset) {
  Value.Check(schema, item);
}
console.timeEnd('Standard');

Advanced Compilation Features

Custom Error Messages

Compiled checkers provide detailed error information with path and context.

interface ValueErrorIterator {
  [Symbol.iterator](): IterableIterator<ValueError>;
  First(): ValueError | undefined;
}

interface ValueError {
  type: ValueErrorType;
  schema: TSchema;
  path: string;
  value: unknown;
  message: string;
}

Usage Examples:

const schema = Type.Object({
  nested: Type.Object({
    items: Type.Array(Type.Number({ minimum: 0 }))
  })
});

const checker = TypeCompiler.Compile(schema);
const invalidData = { nested: { items: [1, -2, 3] } };

if (!checker.Check(invalidData)) {
  for (const error of checker.Errors(invalidData)) {
    console.log(`Path: ${error.path}`);
    console.log(`Message: ${error.message}`);
    console.log(`Value: ${JSON.stringify(error.value)}`);
  }
  // Output:
  // Path: /nested/items/1
  // Message: Expected number to be greater or equal to 0
  // Value: -2
}

Code Inspection

Examine the generated validation code for debugging or optimization.

const User = Type.Object({
  name: Type.String({ minLength: 1 }),
  age: Type.Number({ minimum: 0 })
});

const checker = TypeCompiler.Compile(User);
console.log(checker.Code());

// Generated code example:
// function check(value) {
//   return (
//     typeof value === 'object' && value !== null &&
//     typeof value.name === 'string' && value.name.length >= 1 &&
//     typeof value.age === 'number' && value.age >= 0
//   );
// }

Compilation Limitations

While TypeCompiler supports most TypeBox schemas, some advanced features have limitations:

Supported Features

  • All basic types (String, Number, Boolean, Array, Object, etc.)
  • Union and Intersect types
  • Literal and Enum types
  • Most utility types (Partial, Pick, Omit, etc.)
  • Format validation (email, uuid, date-time, etc.)
  • Numeric constraints (minimum, maximum, multipleOf)
  • String constraints (minLength, maxLength, pattern)
  • Array constraints (minItems, maxItems, uniqueItems)

Limited Support

  • Transform types: Compilation not supported, use Value.Check instead
  • Recursive types: Limited depth compilation
  • Custom formats: Must be registered in FormatRegistry
  • Complex conditional logic: May not optimize effectively

Fallback Strategy:

const TransformSchema = Type.Transform(Type.String())
  .Decode(value => new Date(value))
  .Encode(value => value.toISOString());

// Compilation not supported for transforms
try {
  const checker = TypeCompiler.Compile(TransformSchema);
} catch (error) {
  console.log("Compilation failed, using Value.Check");
  // Fallback to runtime validation
  const isValid = Value.Check(TransformSchema, someValue);
}

Compilation Best Practices

Pre-compile Schemas

Compile schemas once at startup for optimal performance.

// Schema definitions
const schemas = {
  User: Type.Object({
    name: Type.String(),
    email: Type.String({ format: 'email' })
  }),
  Product: Type.Object({
    id: Type.String(),
    price: Type.Number({ minimum: 0 })
  })
};

// Pre-compile all schemas
const checkers = {
  User: TypeCompiler.Compile(schemas.User),
  Product: TypeCompiler.Compile(schemas.Product)
};

// Use compiled checkers in request handlers
function validateUser(userData: unknown) {
  return checkers.User.Check(userData);
}

Error Handling Patterns

function validateWithErrors<T extends TSchema>(
  checker: TypeCheck<T>, 
  value: unknown
): { valid: boolean; errors: ValueError[] } {
  if (checker.Check(value)) {
    return { valid: true, errors: [] };
  }
  
  const errors = Array.from(checker.Errors(value));
  return { valid: false, errors };
}

// Usage
const result = validateWithErrors(userChecker, userData);
if (!result.valid) {
  console.log("Validation errors:", result.errors.map(e => e.message));
}

Integration with Frameworks

// Express.js middleware example
function validateBody<T extends TSchema>(checker: TypeCheck<T>) {
  return (req: Request, res: Response, next: NextFunction) => {
    if (checker.Check(req.body)) {
      next();
    } else {
      const errors = Array.from(checker.Errors(req.body));
      res.status(400).json({ 
        error: "Validation failed", 
        details: errors.map(e => ({ path: e.path, message: e.message }))
      });
    }
  };
}

// Usage
app.post('/users', validateBody(userChecker), (req, res) => {
  // req.body is guaranteed to be valid User type
  const user = req.body as Static<typeof User>;
  // ... handle request
});

Type Interfaces

interface TypeCheck<T extends TSchema> {
  /** Check if value matches the compiled schema */
  Check(value: unknown): value is Static<T>;
  /** Get iterator of validation errors */
  Errors(value: unknown): ValueErrorIterator;
  /** Get the generated validation code */
  Code(): string;
}

interface TypeCompilerCodegenOptions {
  /** Name for the generated validation function */
  functionName?: string;
  /** Include source mapping information */
  sourceMaps?: boolean;
  /** Optimization strategy */
  optimize?: 'size' | 'speed';
}

// Re-exported from errors module
interface ValueError {
  type: ValueErrorType;
  schema: TSchema;
  path: string;
  value: unknown;
  message: string;
}

interface ValueErrorIterator extends IterableIterator<ValueError> {
  /** Get the first error without iteration */
  First(): ValueError | undefined;
}

Install with Tessl CLI

npx tessl i tessl/npm-sinclair--typebox

docs

additional-namespaces.md

advanced-types.md

basic-types.md

compilation.md

index.md

javascript-types.md

transforms.md

value-operations.md

tile.json