Security News
Cloudflare Adds Security.txt Setup Wizard
Cloudflare has launched a setup wizard allowing users to easily create and manage a security.txt file for vulnerability disclosure on their websites.
@sinclair/typebox
Advanced tools
The @sinclair/typebox package is a TypeScript utility designed to create type-safe schemas with a consistent syntax. It is primarily used for defining data structures with TypeScript types and validating data at runtime using a separate validation library like Ajv.
Type Creation
Allows the creation of TypeScript types for various data structures such as strings, numbers, objects, arrays, etc. The created types can be used for compile-time type checking and runtime validation.
{"const T = Type.String()"}
Type Composition
Enables the composition of complex types by combining simpler types. This is useful for defining the shape of objects, with optional and required fields.
{"const UserType = Type.Object({ name: Type.String(), age: Type.Optional(Type.Number()) })"}
Type Validation
Provides a way to validate data at runtime against the defined types using a validation library like Ajv. This ensures that the data conforms to the specified schema.
{"const T = Type.String(); const validate = ajv.compile(T); const isValid = validate('hello');"}
Joi is a powerful schema description language and data validator for JavaScript. It allows for detailed descriptions of data structures with a wide range of validation options. Compared to @sinclair/typebox, Joi has a more extensive API and built-in validation without the need for an external library.
Yup is a JavaScript schema builder for value parsing and validation. It defines a schema with an expressive API and handles both validation and error messages. Unlike @sinclair/typebox, Yup includes its own validation methods and does not rely on TypeScript for type definitions.
Zod is a TypeScript-first schema declaration and validation library. It offers a similar experience to @sinclair/typebox by leveraging TypeScript for type safety while also providing runtime validation. Zod's API is designed to be more concise and it includes its own validation logic.
$ npm install @sinclair/typebox --save
import { Static, Type } from 'https://deno.land/x/typebox/src/typebox.ts'
import { Static, Type } from '@sinclair/typebox'
const T = Type.String() // const T = { "type": "string" }
type T = Static<typeof T> // type T = string
TypeBox is a library that builds in-memory JSON Schema objects that can be statically resolved to TypeScript types. The schemas produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox allows one to create a unified type that can be statically checked by the TypeScript compiler and runtime asserted using standard JSON Schema validation.
TypeBox can be used as a simple tool to build up complex schemas or integrated into RPC or REST services to help validate JSON data received over the wire. TypeBox does not provide any JSON schema validation. Please use libraries such as AJV to validate schemas built with this library.
Requires TypeScript 4.3.5 and above.
License MIT
The following demonstrates TypeBox's general usage.
import { Static, Type } from '@sinclair/typebox'
//--------------------------------------------------------------------------------------------
//
// Let's say you have the following type ...
//
//--------------------------------------------------------------------------------------------
type T = {
id: string,
name: string,
timestamp: number
}
//--------------------------------------------------------------------------------------------
//
// ... you can express this type in the following way.
//
//--------------------------------------------------------------------------------------------
const T = Type.Object({ // const T = {
id: Type.String(), // type: 'object',
name: Type.String(), // properties: {
timestamp: Type.Integer() // id: {
}) // type: 'string'
// },
// name: {
// type: 'string'
// },
// timestamp: {
// type: 'integer'
// }
// },
// required: [
// "id",
// "name",
// "timestamp"
// ]
// }
//--------------------------------------------------------------------------------------------
//
// ... then infer back to the original static type this way.
//
//--------------------------------------------------------------------------------------------
type T = Static<typeof T> // type T = {
// id: string,
// name: string,
// timestamp: number
// }
//--------------------------------------------------------------------------------------------
//
// ... then use the type both as JSON schema and as a TypeScript type.
//
//--------------------------------------------------------------------------------------------
function receive(value: T) { // ... as a Type
if(JSON.validate(T, value)) { // ... as a Schema
// ok...
}
}
The following table outlines the TypeBox mappings between TypeScript and JSON schema.
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
│ TypeBox │ TypeScript │ JSON Schema │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Any() │ type T = any │ const T = { } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Unknown() │ type T = unknown │ const T = { } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.String() │ type T = string │ const T = { │
│ │ │ type: 'string' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Number() │ type T = number │ const T = { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Integer() │ type T = number │ const T = { │
│ │ │ type: 'integer' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Boolean() │ type T = boolean │ const T = { │
│ │ │ type: 'boolean' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Null() │ type T = null │ const T = { │
│ │ │ type: 'null' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.RegEx(/foo/) │ type T = string │ const T = { │
│ │ │ type: 'string', │
│ │ │ pattern: 'foo' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Literal(42) │ type T = 42 │ const T = { │
│ │ │ const: 42 │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Array( │ type T = number[] │ const T = { │
│ Type.Number() │ │ type: 'array', │
│ ) │ │ items: { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Object({ │ type T = { │ const T = { │
│ x: Type.Number(), │ x: number, │ type: 'object', │
│ y: Type.Number() │ y: number │ properties: { │
│ }) │ } │ x: { │
│ │ │ type: 'number' │
│ │ │ }, │
│ │ │ y: { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ }, │
│ │ │ required: ['x', 'y'] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Tuple([ │ type T = [number, number] │ const T = { │
│ Type.Number(), │ │ type: 'array', │
│ Type.Number() │ │ items: [ │
│ ]) │ │ { │
│ │ │ type: 'number' │
│ │ │ }, { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ ], │
│ │ │ additionalItems: false, │
│ │ │ minItems: 2, │
│ │ │ maxItems: 2, │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ enum Foo { │ enum Foo { │ const T = { │
│ A, │ A, │ anyOf: [{ │
│ B │ B │ type: 'number', │
│ } │ } │ const: 0 │
│ │ │ }, { │
│ const T = Type.Enum(Foo) │ type T = Foo │ type: 'number', │
│ │ │ const: 1 │
│ │ │ }] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.KeyOf( │ type T = keyof { │ const T = { │
│ Type.Object({ │ x: number, │ enum: ['x', 'y'], │
│ x: Type.Number(), │ y: number │ type: 'string' │
│ y: Type.Number() │ } │ } │
│ }) │ │ │
│ ) │ │ │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Union([ │ type T = string | number │ const T = { │
│ Type.String(), │ │ anyOf: [{ │
│ Type.Number() │ │ type: 'string' │
│ ]) │ │ }, { │
│ │ │ type: 'number' │
│ │ │ }] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Intersect([ │ type T = { │ const T = { │
│ Type.Object({ │ x: number │ allOf: [{ │
│ x: Type.Number() │ } & { │ type: 'object', │
│ }), │ y: number │ properties: { │
│ Type.Object({ │ } │ a: { │
│ y: Type.Number() │ │ type: 'number' │
│ }) │ │ } │
│ }) │ │ }, │
│ │ │ required: ['a'] │
│ │ │ }, { │
│ │ │ type: 'object', │
│ │ │ properties: { │
│ │ │ b: { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ }, │
│ │ │ required: ['b'] │
│ │ │ }] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Record( │ type T = { │ const T = { │
│ Type.String(), │ [key: string]: number │ type: 'object', │
│ Type.Number() │ } │ patternProperties: { │
│ ) │ │ '^.*$': { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Partial( │ type T = Partial<{ │ const T = { │
│ Type.Object({ │ x: number, │ type: 'object', │
│ x: Type.Number(), │ y: number │ properties: { │
│ y: Type.Number() | }> │ x: { │
│ }) │ │ type: 'number' │
│ ) │ │ }, │
│ │ │ y: { │
│ │ │ type: 'number' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Required( │ type T = Required<{ │ const T = { │
│ Type.Object({ │ x?: number, │ type: 'object', │
│ x: Type.Optional( │ y?: number │ properties: { │
│ Type.Number() | }> │ x: { │
│ ), │ │ type: 'number' │
│ y: Type.Optional( │ │ }, │
│ Type.Number() │ │ y: { │
│ ) │ │ type: 'number' │
│ }) │ │ } │
│ ) │ │ }, │
│ │ │ required: ['x', 'y'] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Pick( │ type T = Pick<{ │ const T = { │
│ Type.Object({ │ x: number, │ type: 'object', │
│ x: Type.Number(), │ y: number │ properties: { │
│ y: Type.Number(), | }, 'x'> │ x: { │
│ }), ['x'] │ │ type: 'number' │
│ ) │ │ } │
│ │ │ }, │
│ │ │ required: ['x'] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Omit( │ type T = Omit<{ │ const T = { │
│ Type.Object({ │ x: number, │ type: 'object', │
│ x: Type.Number(), │ y: number │ properties: { │
│ y: Type.Number(), | }, 'x'> │ y: { │
│ }), ['x'] │ │ type: 'number' │
│ ) │ │ } │
│ │ │ }, │
│ │ │ required: ['y'] │
│ │ │ } │
│ │ │ │
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
TypeBox provides modifiers that can be applied to an objects properties. This allows for optional
and readonly
to be applied to that property. The following table illustates how they map between TypeScript and JSON Schema.
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
│ TypeBox │ TypeScript │ JSON Schema │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Object({ │ type T = { │ const T = { │
│ name: Type.Optional( │ name?: string, │ type: 'object', │
│ Type.String(), │ } │ properties: { │
│ ) │ │ name: { │
│ }) │ │ type: 'string' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Object({ │ type T = { │ const T = { │
│ name: Type.Readonly( │ readonly name: string, │ type: 'object', │
│ Type.String(), │ } │ properties: { │
│ ) │ │ name: { │
│ }) │ │ type: 'string' │
│ │ │ } │
│ │ │ }, │
│ │ │ required: ['name'] │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Object({ │ type T = { │ const T = { │
│ name: Type.ReadonlyOptional( │ readonly name?: string, │ type: 'object', │
│ Type.String(), │ } │ properties: { │
│ ) │ │ name: { │
│ }) │ │ type: 'string' │
│ │ │ } │
│ │ │ } │
│ │ │ } │
│ │ │ │
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
You can pass additional JSON schema options on the last argument of any given type. The following are some examples.
// string must be an email
const T = Type.String({ format: 'email' })
// number must be a multiple of 2
const T = Type.Number({ multipleOf: 2 })
// array must have at least 5 integer values
const T = Type.Array(Type.Integer(), { minItems: 5 })
Generic types can be created using functions. The following creates a generic Nullable<T>
type.
import { Type, Static, TSchema } from '@sinclair/typebox'
// type Nullable<T> = T | null
const Nullable = <T extends TSchema>(type: T) => Type.Union([type, Type.Null()])
const T = Nullable(Type.String()) // const T = {
// "anyOf": [{
// type: 'string'
// }, {
// type: 'null'
// }]
// }
type T = Static<typeof T> // type T = string | null
const U = Nullable(Type.Number()) // const U = {
// "anyOf": [{
// type: 'number'
// }, {
// type: 'null'
// }]
// }
type U = Static<typeof U> // type U = number | null
Types can be referenced with Type.Ref(...)
. To reference a type, the target type must specify an $id
.
const T = Type.String({ $id: 'T' }) // const T = {
// $id: 'T',
// type: 'string'
// }
const R = Type.Ref(T) // const R = {
// $ref: 'T'
// }
It can be helpful to organize shared referenced types under a common namespace. The Type.Namespace(...)
function can be used to create a shared definition container for related types. The following creates a Math3D
container and a Vertex
structure that references types in the container.
const Math3D = Type.Namespace({ // const Math3D = {
Vector4: Type.Object({ // $id: 'Math3D',
x: Type.Number(), // definitions: {
y: Type.Number(), // Vector4: {
z: Type.Number(), // type: 'object',
w: Type.Number() // properties: {
}), // x: { type: 'number' },
Vector3: Type.Object({ // y: { type: 'number' },
x: Type.Number(), // z: { type: 'number' },
y: Type.Number(), // w: { type: 'number' }
z: Type.Number() // },
}), // required: ['x', 'y', 'z', 'w']
Vector2: Type.Object({ // },
x: Type.Number(), // Vector3: {
y: Type.Number() // type: 'object',
}) // properties: {
}, { $id: 'Math3D' }) // x: { 'type': 'number' },
// y: { 'type': 'number' },
// z: { 'type': 'number' }
// },
// required: ['x', 'y', 'z']
// },
// Vector2: {
// type: 'object',
// properties: {
// x: { 'type': 'number' },
// y: { 'type': 'number' },
// },
// required: ['x', 'y']
// }
// }
// }
const Vertex = Type.Object({ // const Vertex = {
position: Type.Ref(Math3D, 'Vector4'), // type: 'object',
normal: Type.Ref(Math3D, 'Vector3'), // properties: {
uv: Type.Ref(Math3D, 'Vector2') // position: { $ref: 'Math3D#/definitions/Vector4' },
}) // normal: { $ref: 'Math3D#/definitions/Vector3' },
// uv: { $ref: 'Math3D#/definitions/Vector2' }
// },
// required: ['position', 'normal', 'uv']
// }
Recursive types can be created with the Type.Rec(...)
function. The following creates a Node
type that contains an array of inner Nodes. Note that due to current restrictions on TypeScript inference, it is not possible for TypeBox to statically infer for recursive types. TypeBox will infer the inner recursive type as any
.
const Node = Type.Rec(Self => Type.Object({ // const Node = {
id: Type.String(), // $id: 'Node',
nodes: Type.Array(Self), // $ref: 'Node#/definitions/self',
}), { $id: 'Node' }) // definitions: {
// self: {
// type: 'object',
// properties: {
// id: {
// type: 'string'
// },
// nodes: {
// type: 'array',
// items: {
// $ref: 'Node#/definitions/self'
// }
// }
// }
// }
// }
type Node = Static<typeof Node> // type Node = {
// id: string
// nodes: any[]
//
function visit(node: Node) {
for(const inner of node.nodes) {
visit(inner as Node) // Assert inner as Node
}
}
In addition to JSON schema types, TypeBox provides several extended types that allow for function
and constructor
types to be composed. These additional types are not valid JSON Schema and will not validate using typical JSON Schema validation. However, these types can be used to frame JSON schema and describe callable interfaces that may receive JSON validated data. These types are as follows.
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
│ TypeBox │ TypeScript │ Extended Schema │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Constructor([ │ type T = new ( │ const T = { │
│ Type.String(), │ arg0: string, │ type: 'constructor' │
│ Type.Number(), │ arg1: number │ arguments: [{ │
│ ], Type.Boolean()) │ ) => boolean │ type: 'string' │
│ │ │ }, { │
│ │ │ type: 'number' │
│ │ │ }], │
│ │ │ returns: { │
│ │ │ type: 'boolean' │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Function([ │ type T = ( │ const T = { │
| Type.String(), │ arg0: string, │ type : 'function', │
│ Type.Number(), │ arg1: number │ arguments: [{ │
│ ], Type.Boolean()) │ ) => boolean │ type: 'string' │
│ │ │ }, { │
│ │ │ type: 'number' │
│ │ │ }], │
│ │ │ returns: { │
│ │ │ type: 'boolean' │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Promise( │ type T = Promise<string> │ const T = { │
│ Type.String() │ │ type: 'promise', │
│ ) │ │ item: { │
│ │ │ type: 'string' │
│ │ │ } │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Undefined() │ type T = undefined │ const T = { │
│ │ │ type: 'undefined' │
│ │ │ } │
│ │ │ │
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
│ const T = Type.Void() │ type T = void │ const T = { │
│ │ │ type: 'void' │
│ │ │ } │
│ │ │ │
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
TypeBox includes the properties kind
and modifier
on each underlying schema. These properties are used to help TypeBox statically resolve the schemas to the appropriate TypeScript type as well as apply the appropriate modifiers to an objects properties (such as optional). These properties are not strictly valid JSON schema so in some cases it may be desirable to omit them. TypeBox provides a Type.Strict()
function that will omit these properties if nessasary.
const T = Type.Object({ // const T = {
name: Type.Optional(Type.String()) // kind: Symbol(ObjectKind),
}) // type: 'object',
// properties: {
// name: {
// kind: Symbol(StringKind),
// type: 'string',
// modifier: Symbol(OptionalModifier)
// }
// }
// }
const U = Type.Strict(T) // const U = {
// type: 'object',
// properties: {
// name: {
// type: 'string'
// }
// }
// }
TypeBox does not provide JSON schema validation functionality, so users will need to select an appropriate JSON Schema validator for their language or framework. TypeBox targets JSON Schema draft 2019-09
so any validator capable of draft 2019-09
should be fine. A good library to use for validation in JavaScript environments is AJV. The following example shows setting up AJV 7 to work with TypeBox.
$ npm install ajv ajv-formats --save
//--------------------------------------------------------------------------------------------
//
// Import the 2019 compliant validator from AJV
//
//--------------------------------------------------------------------------------------------
import { Type } from '@sinclair/typebox'
import addFormats from 'ajv-formats'
import Ajv from 'ajv/dist/2019'
//--------------------------------------------------------------------------------------------
//
// Setup AJV validator with the following options and formats
//
//--------------------------------------------------------------------------------------------
const ajv = addFormats(new Ajv({}), [
'date-time',
'time',
'date',
'email',
'hostname',
'ipv4',
'ipv6',
'uri',
'uri-reference',
'uuid',
'uri-template',
'json-pointer',
'relative-json-pointer',
'regex'
]).addKeyword('kind')
.addKeyword('modifier')
//--------------------------------------------------------------------------------------------
//
// Create a TypeBox type
//
//--------------------------------------------------------------------------------------------
const User = Type.Object({
userId: Type.String({ format: 'uuid' }),
email: Type.String({ format: 'email' }),
online: Type.Boolean(),
}, { additionalProperties: false })
//--------------------------------------------------------------------------------------------
//
// Validate Data
//
//--------------------------------------------------------------------------------------------
const ok = ajv.validate(User, {
userId: '68b4b1d8-0db6-468d-b551-02069a692044',
email: 'dave@domain.com',
online: true
}) // -> ok
Referenced types can be added to AJV with the ajv.addSchema(...)
function. The following moves the userId
and email
property types into a Type.Namespace(...)
and registers the box with AJV.
//--------------------------------------------------------------------------------------------
//
// Shared Types
//
//--------------------------------------------------------------------------------------------
const Shared = Type.Namespace({
UserId: Type.String({ format: 'uuid' }),
Email: Type.String({ format: 'email' })
}, { $id: 'Shared' })
//--------------------------------------------------------------------------------------------
//
// Setup Validator and Register Shared Types
//
//--------------------------------------------------------------------------------------------
const ajv = addFormats(new Ajv({}), [...])
.addKeyword('kind')
.addKeyword('modifier')
.addSchema(Shared) // <-- Register Shared Types
//--------------------------------------------------------------------------------------------
//
// Create a TypeBox type
//
//--------------------------------------------------------------------------------------------
const User = Type.Object({
userId: Type.Ref(Shared, 'UserId'),
email: Type.Ref(Shared, 'Email'),
online: Type.Boolean()
}, { additionalProperties: false })
//--------------------------------------------------------------------------------------------
//
// Validate Data
//
//--------------------------------------------------------------------------------------------
const ok = ajv.validate(User, {
userId: '68b4b1d8-0db6-468d-b551-02069a692044',
email: 'dave@domain.com',
online: true
}) // -> ok
Please refer to the official AJV documentation for additional information.
TypeBox can be used to create schemas for OpenAPI, however users should be aware of the various differences between the JSON Schema and OpenAPI specifications. Two common instances where OpenAPI diverges from the JSON Schema specification is OpenAPI's handling of string enum
and nullable
. The following shows how you can use TypeBox to construct these types.
import { Type, Static, TNull, TLiteral, TUnion, TSchema } from '@sinclair/typebox'
//--------------------------------------------------------------------------------------------
//
// Nullable<T>
//
//--------------------------------------------------------------------------------------------
function Nullable<T extends TSchema>(schema: T): TUnion<[T, TNull]> {
return { ...schema, nullable: true } as any
}
const T = Nullable(Type.String()) // const T = {
// type: 'string',
// nullable: true
// }
type T = Static<typeof T> // type T = string | null
//--------------------------------------------------------------------------------------------
//
// StringUnion<[...]>
//
//--------------------------------------------------------------------------------------------
function StringUnion<T extends string[]>(values: [...T]): TUnion<{[K in keyof T]: T[K] }[number]> {
return { enum: values } as any
}
const T = StringUnion(['A', 'B', 'C']) // const T = {
// enum: ['A', 'B', 'C']
// }
type T = Static<typeof T> // type T = 'A' | 'B' | 'C'
FAQs
Json Schema Type Builder with Static Type Resolution for TypeScript
The npm package @sinclair/typebox receives a total of 26,551,729 weekly downloads. As such, @sinclair/typebox popularity was classified as popular.
We found that @sinclair/typebox demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Cloudflare has launched a setup wizard allowing users to easily create and manage a security.txt file for vulnerability disclosure on their websites.
Security News
The Socket Research team breaks down a malicious npm package targeting the legitimate DOMPurify library. It uses obfuscated code to hide that it is exfiltrating browser and crypto wallet data.
Security News
ENISA’s 2024 report highlights the EU’s top cybersecurity threats, including rising DDoS attacks, ransomware, supply chain vulnerabilities, and weaponized AI.