Skip to main content
Deno 2 is finally here πŸŽ‰οΈ
Learn more

πŸ›΅ TypeSchema

Universal adapter for schema validation

License NPM Downloads


Many libraries rely on some sort of type validation. Their maintainers have the choice of either to:

  1. ⁠Implement their own validation logic: which leads to more code to maintain, and we already have many good solutions out there (e.g. zod, arktype, typia)
  2. Couple their code with a specific validation library: which limits adoption by developers who use another
  3. Support multiple validation libraries: which is a burden to keep up-to-date (tRPC picked this one)

There’s no best validation library because there’s always a tradeoff. Each developer chooses the library that makes the most sense to them. TypeSchema solves this problem by easily providing option 3: support multiple validation libraries out-of-the-box.

Features

  • πŸš€ Decouple your code from validation libraries
  • πŸƒ Tiny client footprint, zero dependencies
  • ✨ Easy-to-use, minimal API

Setup

Install TypeSchema with your package manager of choice:

npm npm install @decs/typeschema
Yarn yarn add @decs/typeschema
pnpm pnpm add @decs/typeschema

Usage

import type {Infer, Schema} from '@decs/typeschema';
import {assert, validate} from '@decs/typeschema';

// Use your favorite validation library, e.g. `zod`, `arktype`, `typia`
const schema: Schema<string> = z.string();
const schema: Schema<string> = type('string');
const schema: Schema<string> = typia.createAssert<string>();

// Extracts the schema type
type Type = Infer<typeof schema>; // `string`

// Returns the validated data or throws a `ValidationIssue`
await assert(schema, '123'); // '123'
await assert(schema, 123); // throws `ValidationIssue`

// Returns the validated data or a list of `ValidationIssue`s
await validate(schema, '123'); // {data: '123'}
await validate(schema, 123); // {issues: [`ValidationIssue`]}

API

Types

  • Schema<T>

    Generic interface for schemas
    An union of the schema types of all supported validation libraries

  • Infer<TSchema extends Schema>

    Extracts the equivalent TypeScript type of a schema

  • ValidationIssue

    Generic interface for validation issues
    Includes a message: string and an optional path?: Array<string | number | symbol>

Functions

  • assert(schema, data)

    assert<TSchema extends Schema>(
      schema: TSchema,
      data: unknown,
    ): Promise<Infer<Schema>>

    Returns the validated data or throws a ValidationIssue

  • validate(schema, data)

    validate<TSchema extends Schema>(
      schema: TSchema,
      data: unknown,
    ): Promise<{data: Infer<TSchema>} | {issues: Array<ValidationIssue>}>

    Returns the validated data or a list of ValidationIssues

Coverage

Project Popularity Example schema Support
zod GitHub Stars z.string() βœ…
yup GitHub Stars string() βœ…
joi GitHub Stars Joi.string() βœ…
ajv GitHub Stars {type: "string"} ❌
superstruct GitHub Stars string() βœ…
io-ts GitHub Stars t.string βœ…
ow GitHub Stars ow.string ❌
typebox GitHub Stars Type.String() βœ…
typia GitHub Stars typia.createAssert<string>() βœ…
deepkit GitHub Stars is<string> ❌
runtypes GitHub Stars String βœ…
arktype GitHub Stars type('string') βœ…

Custom validations are also supported:

export function assertString(data: unknown): string {
  if (typeof data !== 'string') {
    throw new Error('Expected a string, got: ' + data);
  }
  return data;
}

await assert(assertString, '123'); // '123'
await assert(assertString, 123); // throws `ValidationIssue`

await validate(assertString, '123'); // {data: '123'}
await validate(assertString, 123); // {issues: [`ValidationIssue`]}

Acknowledgements