• Stars
    star
    329
  • Rank 128,030 (Top 3 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created over 1 year ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

๐Ÿ›ต Universal adapter for TypeScript schema validation.

TypeSchema

TypeSchema

โœจ https://typeschema.com โœจ
Universal adapter for schema validation


License Bundle size npm downloads GitHub stars

Setup ย ย โ€ขย ย  API ย ย โ€ขย ย  Coverage ย ย โ€ขย ย  GitHub ย ย โ€ขย ย  npm ย ย โ€ขย ย  Deno


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 (e.g. tRPC)

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 from schema validation libraries
  • ๐Ÿƒ Tiny client footprint, tree-shakeable
  • ๐Ÿ›‹๏ธ Easy-to-use, minimal API

Usage

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

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

// Extracts the schema type
type Output = Infer<typeof schema>; // `string`
type Input = InferIn<typeof schema>; // `string`

// Returns the wrapped schema with access to all its operations
const wrapped = wrap(schema);
await wrapped.validate('123'); // {success: true, data: '123'}
await wrapped.assert('123'); // '123'

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

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

tRPC

You can use any supported schema on tRPC through the wrap function:

import {wrap} from '@decs/typeschema';
import {initTRPC} from '@trpc/server';
import {object, string} from 'valibot';

// Use your favorite validation library, e.g. `valibot`
const schema = object({name: string()});

const t = initTRPC.create();
const appRouter = t.router({
  hello: t.procedure
    .input(wrap(schema)) // like this
    .query(({input}) => `Hello, ${input.name}!`),
});

Coverage

TypeSchema supports all major schema validation libraries:

Project Popularity wrap validate
assert
Infer InferIn Example schema
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
ow1 GitHub stars โœ… โœ… โœ… โœ… ow.string
typia GitHub stars โœ… โœ… โœ… โœ… typia.createAssert<string>()
valibot GitHub stars โœ… โœ… โœ… โœ… string()
typebox GitHub stars โœ… โœ… โœ… โœ… Type.String()
deepkit GitHub stars โœ… โœ… โŒ โŒ typeOf<string>()
effect GitHub stars โœ… โœ… โœ… โœ… S.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 validate(assertString, '123'); // {success: true, data: '123'}
await validate(assertString, 123); // {success: false, issues: [`ValidationIssue`]}

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

Setup

Install TypeSchema with your package manager of choice:

npm npm install @decs/typeschema
Yarn yarn add @decs/typeschema
pnpm pnpm add @decs/typeschema
Deno https://deno.land/x/typeschema

API

Types

  • Schema

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

  • TypeSchema<TOutput, TInput = TOutput>

    Interface for a wrapped schema, exposing all its operations

  • Infer<TSchema extends Schema>

    Extracts the output type of a schema

  • InferIn<TSchema extends Schema>

    Extracts the input type of a schema

  • ValidationIssue

    Generic interface for validation issues
    Includes a message and an optional path

Functions

  • wrap(schema)

    wrap<TSchema extends Schema>(
      schema: TSchema,
    ): TypeSchema<Infer<TSchema>, InferIn<TSchema>>

    Returns the wrapped schema with access to all its operations

  • validate(schema, data)

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

    Returns the validated data or a list of ValidationIssues

  • assert(schema, data)

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

    Returns the validated data or throws an AggregateError

Acknowledgements

Footnotes

  1. For ow, only v0.28.2 is supported (sindresorhus/ow#248) โ†ฉ