TypeSchema
β¨ https://typeschema.com β¨
Universal adapter for schema validation
Setup Β Β β’Β Β API Β Β β’Β Β Coverage Β Β β’Β Β GitHub Β Β β’Β Β npm Β Β β’Β Β Deno
Many libraries rely on some sort of type validation. Their maintainers have the choice of either to:
- β 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) - Couple their code with a specific validation library: which limits adoption by developers who use another
- 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 |
validateassert |
Infer |
InferIn |
Example schema |
|---|---|---|---|---|---|---|
| zod | β | β | β | β | z.string() |
|
| yup | β | β | β | β | string() |
|
| joi | β | β | β | β | Joi.string() |
|
| ajv | β | β | β | β | {type: "string"} |
|
| superstruct | β | β | β | β | string() |
|
| io-ts | β | β | β | β | t.string |
|
| valibot | β | β | β | β | string() |
|
| typebox | β | β | β | β | Type.String() |
|
| typia | β | β | β | β | typia.createAssert<string>() |
|
| ow[^1] | β | β | β | β | ow.string |
|
| effect | β | β | β | β | S.string |
|
| arktype | β | β | β | β | type('string') |
|
| deepkit | β | β | β | β | typeOf<string>() |
|
| runtypes | β | β | β | β | String |
[^1]: For ow, only v0.28.2 is supported (sindresorhus/ow#248)
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
SchemaGeneric interface for schemas
An union of the schema types of all supported librariesTypeSchema<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
ValidationIssueGeneric interface for validation issues
Includes amessageand an optionalpath
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
ValidationIssuesassert(schema, data)assert<TSchema extends Schema>( schema: TSchema, data: unknown, ): Promise<Infer<TSchema>>
Returns the validated data or throws an
AggregateError
Acknowledgements
- Inspired by tRPCβs input & output validators
- Adapter architecture inspired by @ecyrbeβs suggestions
- API definition inspired by @colinhacksβs proposal
- Logo designed by flaticon