@sinclair/typebox 0.34.41 → 0.34.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/readme.md CHANGED
@@ -1,1861 +1,1863 @@
1
- <div align='center'>
2
-
3
- <h1>TypeBox</h1>
4
-
5
- <p>Json Schema Type Builder with Static Type Resolution for TypeScript</p>
6
-
7
- <img src="https://raw.githubusercontent.com/sinclairzx81/typebox/refs/heads/master/typebox.png" />
8
-
9
- <br />
10
- <br />
11
-
12
- [![npm version](https://badge.fury.io/js/%40sinclair%2Ftypebox.svg)](https://badge.fury.io/js/%40sinclair%2Ftypebox)
13
- [![Downloads](https://img.shields.io/npm/dm/%40sinclair%2Ftypebox.svg)](https://www.npmjs.com/package/%40sinclair%2Ftypebox)
14
- [![Build](https://github.com/sinclairzx81/typebox/actions/workflows/build.yml/badge.svg)](https://github.com/sinclairzx81/typebox/actions/workflows/build.yml)
15
- [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
16
-
17
- </div>
18
-
19
- <a name="Install"></a>
20
-
21
- ## Install
22
-
23
- ```bash
24
- $ npm install @sinclair/typebox --save
25
- ```
26
-
27
- ## Example
28
-
29
- ```typescript
30
- import { Type, type Static } from '@sinclair/typebox'
31
-
32
- const T = Type.Object({ // const T = {
33
- x: Type.Number(), // type: 'object',
34
- y: Type.Number(), // required: ['x', 'y', 'z'],
35
- z: Type.Number() // properties: {
36
- }) // x: { type: 'number' },
37
- // y: { type: 'number' },
38
- // z: { type: 'number' }
39
- // }
40
- // }
41
-
42
- type T = Static<typeof T> // type T = {
43
- // x: number,
44
- // y: number,
45
- // z: number
46
- // }
47
- ```
48
-
49
-
50
- <a name="Overview"></a>
51
-
52
- ## Overview
53
-
54
- TypeBox is a runtime type builder that creates in-memory Json Schema objects that infer as TypeScript types. The schematics produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox offers a unified type that can be statically checked by TypeScript and runtime asserted using standard Json Schema validation.
55
-
56
- This library is designed to allow Json Schema to compose similar to how types compose within TypeScript's type system. It can be used as a simple tool to build up complex schematics or integrated into REST and RPC services to help validate data received over the wire.
57
-
58
- License MIT
59
-
60
- ## Contents
61
- - [Install](#install)
62
- - [Overview](#overview)
63
- - [Usage](#usage)
64
- - [Types](#types)
65
- - [Json](#types-json)
66
- - [JavaScript](#types-javascript)
67
- - [Options](#types-options)
68
- - [Properties](#types-properties)
69
- - [Generics](#types-generics)
70
- - [Recursive](#types-recursive)
71
- - [Modules](#types-modules)
72
- - [Template Literal](#types-template-literal)
73
- - [Indexed](#types-indexed)
74
- - [Mapped](#types-mapped)
75
- - [Conditional](#types-conditional)
76
- - [Transform](#types-transform)
77
- - [Guard](#types-guard)
78
- - [Unsafe](#types-unsafe)
79
- - [Values](#values)
80
- - [Assert](#values-assert)
81
- - [Create](#values-create)
82
- - [Clone](#values-clone)
83
- - [Check](#values-check)
84
- - [Convert](#values-convert)
85
- - [Default](#values-default)
86
- - [Clean](#values-clean)
87
- - [Cast](#values-cast)
88
- - [Decode](#values-decode)
89
- - [Encode](#values-decode)
90
- - [Parse](#values-parse)
91
- - [Equal](#values-equal)
92
- - [Hash](#values-hash)
93
- - [Diff](#values-diff)
94
- - [Patch](#values-patch)
95
- - [Errors](#values-errors)
96
- - [Mutate](#values-mutate)
97
- - [Pointer](#values-pointer)
98
- - [Syntax](#syntax)
99
- - [Create](#syntax-create)
100
- - [Parameters](#syntax-parameters)
101
- - [Generics](#syntax-generics)
102
- - [Options](#syntax-options)
103
- - [NoInfer](#syntax-no-infer)
104
- - [TypeRegistry](#typeregistry)
105
- - [Type](#typeregistry-type)
106
- - [Format](#typeregistry-format)
107
- - [TypeCheck](#typecheck)
108
- - [Ajv](#typecheck-ajv)
109
- - [TypeCompiler](#typecheck-typecompiler)
110
- - [TypeMap](#typemap)
111
- - [Usage](#typemap-usage)
112
- - [TypeSystem](#typesystem)
113
- - [Policies](#typesystem-policies)
114
- - [Error Function](#error-function)
115
- - [Workbench](#workbench)
116
- - [Codegen](#codegen)
117
- - [Ecosystem](#ecosystem)
118
- - [Benchmark](#benchmark)
119
- - [Compile](#benchmark-compile)
120
- - [Validate](#benchmark-validate)
121
- - [Compression](#benchmark-compression)
122
- - [Contribute](#contribute)
123
-
124
- <a name="usage"></a>
125
-
126
- ## Usage
127
-
128
- The following shows general usage.
129
-
130
- ```typescript
131
- import { Type, type Static } from '@sinclair/typebox'
132
-
133
- //--------------------------------------------------------------------------------------------
134
- //
135
- // Let's say you have the following type ...
136
- //
137
- //--------------------------------------------------------------------------------------------
138
-
139
- type T = {
140
- id: string,
141
- name: string,
142
- timestamp: number
143
- }
144
-
145
- //--------------------------------------------------------------------------------------------
146
- //
147
- // ... you can express this type in the following way.
148
- //
149
- //--------------------------------------------------------------------------------------------
150
-
151
- const T = Type.Object({ // const T = {
152
- id: Type.String(), // type: 'object',
153
- name: Type.String(), // properties: {
154
- timestamp: Type.Integer() // id: {
155
- }) // type: 'string'
156
- // },
157
- // name: {
158
- // type: 'string'
159
- // },
160
- // timestamp: {
161
- // type: 'integer'
162
- // }
163
- // },
164
- // required: [
165
- // 'id',
166
- // 'name',
167
- // 'timestamp'
168
- // ]
169
- // }
170
-
171
- //--------------------------------------------------------------------------------------------
172
- //
173
- // ... then infer back to the original static type this way.
174
- //
175
- //--------------------------------------------------------------------------------------------
176
-
177
- type T = Static<typeof T> // type T = {
178
- // id: string,
179
- // name: string,
180
- // timestamp: number
181
- // }
182
-
183
- //--------------------------------------------------------------------------------------------
184
- //
185
- // ... or use the type to parse JavaScript values.
186
- //
187
- //--------------------------------------------------------------------------------------------
188
-
189
- import { Value } from '@sinclair/typebox/value'
190
-
191
- const R = Value.Parse(T, value) // const R: {
192
- // id: string,
193
- // name: string,
194
- // timestamp: number
195
- // }
196
- ```
197
-
198
- <a name='types'></a>
199
-
200
- ## Types
201
-
202
- TypeBox types are Json Schema fragments that compose into more complex types. Each fragment is structured such that any Json Schema compliant validator can runtime assert a value the same way TypeScript will statically assert a type. TypeBox offers a set of Json Types which are used to create Json Schema compliant schematics as well as a JavaScript type set used to create schematics for constructs native to JavaScript.
203
-
204
- <a name='types-json'></a>
205
-
206
- ### Json Types
207
-
208
- The following table lists the supported Json types. These types are fully compatible with the Json Schema Draft 7 specification.
209
-
210
- ```typescript
211
- ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
212
- │ TypeBox │ TypeScript │ Json Schema │
213
- │ │ │ │
214
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
215
- const T = Type.Any() type T = any const T = { }
216
- │ │ │ │
217
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
218
- const T = Type.Unknown() type T = unknown const T = { }
219
- │ │ │ │
220
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
221
- const T = Type.String() type T = string const T = {
222
- │ │ │ type: 'string' │
223
- }
224
- │ │ │
225
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
226
- const T = Type.Number() type T = number const T = {
227
- │ │ │ type: 'number' │
228
- }
229
- │ │ │
230
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
231
- const T = Type.Integer() type T = number const T = {
232
- │ │ │ type: 'integer' │
233
- }
234
- │ │ │
235
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
236
- const T = Type.Boolean() type T = boolean const T = {
237
- │ │ │ type: 'boolean' │
238
- }
239
- │ │ │
240
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
241
- const T = Type.Null() type T = null const T = {
242
- │ │ │ type: 'null' │
243
- }
244
- │ │ │
245
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
246
- const T = Type.Literal(42) type T = 42 const T = {
247
- │ │ │ const: 42, │
248
- type: 'number'
249
- │ │ │ }
250
- │ │ │
251
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
252
- const T = Type.Array( type T = number[] const T = {
253
- │ Type.Number() │ │ type: 'array', │
254
- ) items: {
255
- │ │ type: 'number'
256
- │ │ }
257
- │ │ │ }
258
- │ │ │
259
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
260
- const T = Type.Object({ type T = { const T = {
261
- │ x: Type.Number(), │ x: number, │ type: 'object', │
262
- y: Type.Number() y: number required: ['x', 'y'],
263
- }) } properties: {
264
- x: {
265
- type: 'number'
266
- │ │ │ },
267
- │ │ │ y: {
268
- │ │ │ type: 'number'
269
- │ │ │ }
270
- │ │ │ }
271
- │ │ │ }
272
- │ │ │
273
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
274
- const T = Type.Tuple([ type T = [number, number] const T = {
275
- │ Type.Number(), │ │ type: 'array', │
276
- Type.Number() items: [{ │
277
- ]) │ │ type: 'number'
278
- │ │ }, {
279
- │ │ type: 'number' │
280
- │ │ │ }],
281
- │ │ │ additionalItems: false,
282
- │ │ │ minItems: 2,
283
- │ │ │ maxItems: 2
284
- │ │ │ }
285
- │ │ │
286
- │ │ │
287
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
288
- enum Foo { enum Foo { const T = {
289
- │ A, │ A, │ anyOf: [{ │
290
- B B type: 'number',
291
- } │ } const: 0
292
- }, {
293
- const T = Type.Enum(Foo) type T = Foo type: 'number',
294
- │ │ │ const: 1
295
- }]
296
- │ │ │ }
297
- │ │ │
298
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
299
- const T = Type.Const({ type T = { const T = {
300
- │ x: 1, │ readonly x: 1, │ type: 'object', │
301
- y: 2, readonly y: 2 required: ['x', 'y'],
302
- } as const) } │ properties: {
303
- x: {
304
- type: 'number',
305
- │ │ │ const: 1
306
- │ │ │ },
307
- │ │ │ y: {
308
- │ │ │ type: 'number',
309
- │ │ │ const: 2
310
- │ │ │ }
311
- │ │ │ }
312
- │ │ │ }
313
- │ │ │
314
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
315
- const T = Type.KeyOf( type T = keyof { const T = {
316
- │ Type.Object({ │ x: number, │ anyOf: [{ │
317
- x: Type.Number(), y: number │ type: 'string',
318
- y: Type.Number() } const: 'x'
319
- }) }, {
320
- │ ) type: 'string',
321
- │ │ const: 'y'
322
- │ │ }]
323
- │ │ │ }
324
- │ │ │
325
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
326
- const T = Type.Union([ type T = string | number const T = {
327
- │ Type.String(), │ │ anyOf: [{ │
328
- Type.Number() type: 'string'
329
- ]) │ │ }, {
330
- │ │ type: 'number' │
331
- │ │ }]
332
- │ │ │ }
333
- │ │ │
334
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
335
- const T = Type.Intersect([ type T = { const T = {
336
- │ Type.Object({ │ x: number │ allOf: [{ │
337
- x: Type.Number() } & { type: 'object',
338
- }), y: number │ required: ['x'],
339
- Type.Object({ │ } properties: {
340
- y: Type.Number() │ x: {
341
- │ }) │ type: 'number'
342
- ]) │ │ }
343
- │ │ }
344
- │ │ }, {
345
- │ │ │ type: 'object', |
346
- │ │ │ required: ['y'],
347
- │ │ │ properties: { │
348
- │ │ │ y: {
349
- │ │ │ type: 'number'
350
- │ │ │ }
351
- │ │ │ }
352
- │ │ │ }]
353
- │ │ │ }
354
- │ │ │
355
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
356
- const T = Type.Composite([ type T = { const T = {
357
- │ Type.Object({ │ x: number, │ type: 'object', │
358
- x: Type.Number() y: number required: ['x', 'y'],
359
- }), } properties: {
360
- Type.Object({ x: {
361
- y: Type.Number() type: 'number'
362
- }) │ │ },
363
- ]) │ │ y: {
364
- │ │ type: 'number'
365
- │ │ }
366
- │ │ │ }
367
- │ │ │ }
368
- │ │ │
369
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
370
- const T = Type.Never() type T = never const T = {
371
- │ │ │ not: {} │
372
- }
373
- │ │ │
374
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
375
- const T = Type.Not( | type T = unknown const T = {
376
- │ Type.String() │ │ not: { │
377
- ) │ │ type: 'string'
378
- │ │ }
379
- │ │ }
380
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
381
- const T = Type.Extends( type T = const T = {
382
- │ Type.String(), │ string extends number │ const: false, │
383
- Type.Number(), ? true │ type: 'boolean'
384
- │ Type.Literal(true), : false } │
385
- │ Type.Literal(false)
386
- )
387
- │ │ │
388
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
389
- const T = Type.Extract( type T = Extract< const T = {
390
- │ Type.Union([ │ string | number, │ type: 'string' │
391
- Type.String(), string }
392
- Type.Number(), >
393
- ]),
394
- Type.String() │ │
395
- ) │ │ │
396
- │ │ │
397
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
398
- const T = Type.Exclude( type T = Exclude< const T = {
399
- │ Type.Union([ │ string | number, │ type: 'number' │
400
- Type.String(), string }
401
- Type.Number(), >
402
- ]),
403
- Type.String() │ │
404
- ) │ │ │
405
- │ │ │
406
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
407
- const T = Type.Mapped( type T = { const T = {
408
- │ Type.Union([ │ [_ in 'x' | 'y'] : number │ type: 'object', │
409
- Type.Literal('x'),} required: ['x', 'y'],
410
- Type.Literal('y') properties: {
411
- ]), x: {
412
- () => Type.Number() │ │ type: 'number'
413
- ) │ │ },
414
- │ │ y: {
415
- │ │ type: 'number'
416
- │ │ │ }
417
- │ │ │ }
418
- │ │ │ }
419
- │ │ │
420
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
421
- const U = Type.Union([ type U = 'open' | 'close' const T = {
422
- │ Type.Literal('open'), │ │ type: 'string', │
423
- Type.Literal('close') │ type T = `on${U}` │ pattern: '^on(open|close)$'
424
- ]) │ │ }
425
-
426
- const T = Type │ │
427
- .TemplateLiteral([ │ │ │
428
- Type.Literal('on'), │ │ │
429
- U │ │ │
430
- ]) │ │ │
431
- │ │ │
432
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
433
- const T = Type.Record( type T = Record< const T = {
434
- │ Type.String(), │ string, │ type: 'object', │
435
- Type.Number() number patternProperties: {
436
- ) > │ '^.*$': {
437
- type: 'number'
438
- }
439
- │ │ │ }
440
- │ │ │ }
441
- │ │ │
442
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
443
- const T = Type.Partial( type T = Partial<{ const T = {
444
- │ Type.Object({ │ x: number, │ type: 'object', │
445
- x: Type.Number(), y: number properties: {
446
- y: Type.Number() | }> x: {
447
- }) │ type: 'number'
448
- │ ) },
449
- │ │ y: {
450
- │ │ type: 'number'
451
- │ │ │ }
452
- │ │ │ }
453
- │ │ │ }
454
- │ │ │
455
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
456
- const T = Type.Required( type T = Required<{ const T = {
457
- │ Type.Object({ │ x?: number, │ type: 'object', │
458
- x: Type.Optional( y?: number required: ['x', 'y'],
459
- Type.Number() | }> properties: {
460
- ), x: {
461
- y: Type.Optional( │ type: 'number'
462
- Type.Number() │ │ },
463
- ) │ │ y: {
464
- }) │ │ type: 'number'
465
- ) │ │ }
466
- │ │ }
467
- │ │ }
468
- │ │ │
469
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
470
- const T = Type.Pick( type T = Pick<{ const T = {
471
- │ Type.Object({ │ x: number, │ type: 'object', │
472
- x: Type.Number(), y: number │ required: ['x'],
473
- y: Type.Number() }, 'x'> properties: {
474
- }), ['x'] | x: { │
475
- │ ) │ type: 'number'
476
- }
477
- │ │ }
478
- │ │ │ }
479
- │ │ │
480
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
481
- const T = Type.Omit( type T = Omit<{ const T = {
482
- │ Type.Object({ │ x: number, │ type: 'object', │
483
- x: Type.Number(), y: number │ required: ['y'],
484
- y: Type.Number() }, 'x'> properties: {
485
- }), ['x'] | y: { │
486
- │ ) │ type: 'number'
487
- }
488
- │ │ }
489
- │ │ │ }
490
- │ │ │
491
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
492
- const T = Type.Index( type T = { const T = {
493
- │ Type.Object({ │ x: number, │ type: 'number' │
494
- x: Type.Number(), y: string }
495
- y: Type.String() }['x']
496
- }), ['x']
497
- │ ) │ │
498
- │ │ │
499
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
500
- const A = Type.Tuple([ type A = [0, 1] const T = {
501
- │ Type.Literal(0), │ type B = [2, 3] │ type: 'array', │
502
- Type.Literal(1) │ type T = [ items: [
503
- ]) │ ...A, { const: 0 },
504
- const B = Type.Tuple([ ...B │ { const: 1 },
505
- | Type.Literal(2), │ ] │ { const: 2 }, │
506
- | Type.Literal(3) │ { const: 3 }
507
- │ ]) │ ],
508
- │ const T = Type.Tuple([ │ │ additionalItems: false,
509
- | ...Type.Rest(A), │ │ minItems: 4,
510
- | ...Type.Rest(B) │ │ maxItems: 4
511
- │ ]) │ │ }
512
-
513
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
514
- const T = Type.Uncapitalize( type T = Uncapitalize< const T = {
515
- │ Type.Literal('Hello') │ 'Hello' │ type: 'string', │
516
- ) > const: 'hello'
517
- }
518
-
519
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
520
- const T = Type.Capitalize( type T = Capitalize< const T = {
521
- │ Type.Literal('hello') │ 'hello' │ type: 'string', │
522
- ) > const: 'Hello'
523
- }
524
-
525
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
526
- const T = Type.Uppercase( type T = Uppercase< const T = {
527
- │ Type.Literal('hello') │ 'hello' │ type: 'string', │
528
- ) > const: 'HELLO'
529
- }
530
-
531
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
532
- const T = Type.Lowercase( type T = Lowercase< const T = {
533
- │ Type.Literal('HELLO') │ 'HELLO' │ type: 'string', │
534
- ) > const: 'hello'
535
- }
536
-
537
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
538
- const R = Type.Ref('T') type R = unknown const R = { $ref: 'T' }
539
- │ │ │ │
540
- └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
541
- ```
542
-
543
- <a name='types-javascript'></a>
544
-
545
- ### JavaScript Types
546
-
547
- TypeBox provides an extended type set that can be used to create schematics for common JavaScript constructs. These types can not be used with any standard Json Schema validator; but can be used to frame schematics for interfaces that may receive Json validated data. JavaScript types are prefixed with the `[JavaScript]` JSDoc comment for convenience. The following table lists the supported types.
548
-
549
- ```typescript
550
- ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
551
- │ TypeBox │ TypeScript │ Extended Schema │
552
- │ │ │ │
553
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
554
- const T = Type.Constructor([ type T = new ( const T = {
555
- │ Type.String(), │ arg0: string, │ type: 'Constructor', │
556
- Type.Number() arg0: number parameters: [{
557
- ], Type.Boolean()) ) => boolean type: 'string'
558
- }, {
559
- │ type: 'number' │
560
- │ │ │ }],
561
- │ │ │ returns: {
562
- │ │ │ type: 'boolean'
563
- │ │ │ }
564
- │ │ │ }
565
- │ │ │
566
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
567
- const T = Type.Function([ type T = ( const T = {
568
- | Type.String(), │ arg0: string, │ type: 'Function', │
569
- Type.Number() arg1: number parameters: [{
570
- │ ], Type.Boolean()) ) => boolean type: 'string'
571
- }, {
572
- │ type: 'number' │
573
- │ │ │ }],
574
- │ │ │ returns: {
575
- │ │ │ type: 'boolean'
576
- │ │ │ }
577
- │ │ │ }
578
- │ │ │
579
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
580
- const T = Type.Promise( type T = Promise<string> const T = {
581
- │ Type.String() │ │ type: 'Promise', │
582
- ) item: {
583
- │ │ type: 'string' │
584
- │ │ }
585
- │ │ │ }
586
- │ │ │
587
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
588
- const T = type T = const T = {
589
- │ Type.AsyncIterator( │ AsyncIterableIterator< │ type: 'AsyncIterator', │
590
- Type.String() string items: {
591
- ) > type: 'string'
592
- }
593
- }
594
- │ │ │
595
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
596
- const T = Type.Iterator( type T = const T = {
597
- │ Type.String() │ IterableIterator<string> │ type: 'Iterator', │
598
- ) items: {
599
- type: 'string'
600
- │ │ }
601
- │ │ │ }
602
- │ │ │
603
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
604
- const T = Type.RegExp(/abc/i) type T = string const T = {
605
- │ │ │ type: 'RegExp' │
606
- source: 'abc'
607
- │ │ │ flags: 'i'
608
- │ │ │ }
609
- │ │ │
610
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
611
- const T = Type.Uint8Array() type T = Uint8Array const T = {
612
- │ │ │ type: 'Uint8Array' │
613
- }
614
- │ │ │
615
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
616
- const T = Type.Date() type T = Date const T = {
617
- │ │ │ type: 'Date' │
618
- }
619
- │ │ │
620
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
621
- const T = Type.Undefined() type T = undefined const T = {
622
- │ │ │ type: 'undefined' │
623
- }
624
- │ │ │
625
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
626
- const T = Type.Symbol() type T = symbol const T = {
627
- │ │ │ type: 'symbol' │
628
- }
629
- │ │ │
630
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
631
- const T = Type.BigInt() type T = bigint const T = {
632
- │ │ │ type: 'bigint' │
633
- }
634
- │ │ │
635
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
636
- const T = Type.Void() type T = void const T = {
637
- │ │ │ type: 'void' │
638
- }
639
- │ │ │
640
- └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
641
- ```
642
-
643
- <a name='types-options'></a>
644
-
645
- ### Options
646
-
647
- You can pass Json Schema options on the last argument of any given type. Option hints specific to each type are provided for convenience.
648
-
649
- ```typescript
650
- // String must be an email
651
- const T = Type.String({ // const T = {
652
- format: 'email' // type: 'string',
653
- }) // format: 'email'
654
- // }
655
-
656
- // Number must be a multiple of 2
657
- const T = Type.Number({ // const T = {
658
- multipleOf: 2 // type: 'number',
659
- }) // multipleOf: 2
660
- // }
661
-
662
- // Array must have at least 5 integer values
663
- const T = Type.Array(Type.Integer(), { // const T = {
664
- minItems: 5 // type: 'array',
665
- }) // minItems: 5,
666
- // items: {
667
- // type: 'integer'
668
- // }
669
- // }
670
- ```
671
-
672
- <a name='types-properties'></a>
673
-
674
- ### Properties
675
-
676
- Object properties can be modified with Readonly and Optional. The following table shows how these modifiers map between TypeScript and Json Schema.
677
-
678
- ```typescript
679
- ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
680
- │ TypeBox │ TypeScript │ Json Schema │
681
- │ │ │ │
682
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
683
- const T = Type.Object({ type T = { const T = {
684
- │ name: Type.ReadonlyOptional( │ readonly name?: string │ type: 'object', │
685
- Type.String() } properties: {
686
- ) name: {
687
- │ }) │ type: 'string'
688
- │ │ }
689
- │ │ }
690
- │ │ │ }
691
- │ │ │
692
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
693
- const T = Type.Object({ type T = { const T = {
694
- │ name: Type.Readonly( │ readonly name: string │ type: 'object', │
695
- Type.String() } properties: {
696
- ) name: {
697
- │ }) │ type: 'string'
698
- │ │ }
699
- │ │ },
700
- │ │ │ required: ['name']
701
- │ │ │ }
702
- │ │ │
703
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
704
- const T = Type.Object({ type T = { const T = {
705
- │ name: Type.Optional( │ name?: string │ type: 'object', │
706
- Type.String() } properties: {
707
- ) name: {
708
- │ }) │ type: 'string'
709
- │ │ }
710
- │ │ }
711
- │ │ │ }
712
- │ │ │
713
- └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
714
- ```
715
-
716
- <a name='types-generics'></a>
717
-
718
- ### Generic Types
719
-
720
- Generic types can be created with generic functions.
721
-
722
- ```typescript
723
- const Nullable = <T extends TSchema>(T: T) => { // type Nullable<T> = T | null
724
- return Type.Union([T, Type.Null()])
725
- }
726
-
727
- const T = Nullable(Type.String()) // type T = Nullable<string>
728
- ```
729
-
730
- <a name='types-recursive'></a>
731
-
732
- ### Recursive Types
733
-
734
- Use the Recursive function to create recursive types.
735
-
736
- ```typescript
737
- const Node = Type.Recursive(This => Type.Object({ // const Node = {
738
- id: Type.String(), // $id: 'Node',
739
- nodes: Type.Array(This) // type: 'object',
740
- }), { $id: 'Node' }) // properties: {
741
- // id: {
742
- // type: 'string'
743
- // },
744
- // nodes: {
745
- // type: 'array',
746
- // items: {
747
- // $ref: 'Node'
748
- // }
749
- // }
750
- // },
751
- // required: [
752
- // 'id',
753
- // 'nodes'
754
- // ]
755
- // }
756
-
757
- type Node = Static<typeof Node> // type Node = {
758
- // id: string
759
- // nodes: Node[]
760
- // }
761
-
762
- function test(node: Node) {
763
- const id = node.nodes[0].nodes[0].id // id is string
764
- }
765
- ```
766
-
767
- <a name='types-modules'></a>
768
-
769
- ### Module Types
770
-
771
- Module types are containers for a set of referential types. Modules act as namespaces, enabling types to reference one another via string identifiers. Modules support both singular and mutually recursive references, as well as deferred dereferencing for computed types such as Partial. Types imported from a module are expressed using the Json Schema `$defs` keyword.
772
-
773
- ```typescript
774
- const Module = Type.Module({
775
- PartialUser: Type.Partial(Type.Ref('User')), // TComputed<'Partial', [TRef<'User'>]>
776
-
777
- User: Type.Object({ // TObject<{
778
- id: Type.String(), // user: TString,
779
- name: Type.String(), // name: TString,
780
- email: Type.String() // email: TString
781
- }), // }>
782
- })
783
- const User = Module.Import('User') // const User: TImport<{...}, 'User'>
784
-
785
- type User = Static<typeof User> // type User = {
786
- // id: string,
787
- // name: string,
788
- // email: string
789
- // }
790
-
791
- const PartialUser = Module.Import('PartialUser') // const PartialUser: TImport<{...}, 'PartialUser'>
792
-
793
- type PartialUser = Static<typeof PartialUser> // type PartialUser = {
794
- // id?: string,
795
- // name?: string,
796
- // email?: string
797
- // }
798
- ```
799
-
800
- <a name='types-template-literal'></a>
801
-
802
- ### Template Literal Types
803
-
804
- TypeBox supports template literal types with the TemplateLiteral function. This type can be created using a syntax similar to the TypeScript template literal syntax or composed from exterior types. TypeBox encodes template literals as regular expressions which enables the template to be checked by Json Schema validators. This type also supports regular expression parsing that enables template patterns to be used for generative types. The following shows both TypeScript and TypeBox usage.
805
-
806
- ```typescript
807
- // TypeScript
808
-
809
- type K = `prop${'A'|'B'|'C'}` // type T = 'propA' | 'propB' | 'propC'
810
-
811
- type R = Record<K, string> // type R = {
812
- // propA: string
813
- // propB: string
814
- // propC: string
815
- // }
816
-
817
- // TypeBox
818
-
819
- const K = Type.TemplateLiteral('prop${A|B|C}') // const K: TTemplateLiteral<[
820
- // TLiteral<'prop'>,
821
- // TUnion<[
822
- // TLiteral<'A'>,
823
- // TLiteral<'B'>,
824
- // TLiteral<'C'>,
825
- // ]>
826
- // ]>
827
-
828
- const R = Type.Record(K, Type.String()) // const R: TObject<{
829
- // propA: TString,
830
- // propB: TString,
831
- // propC: TString,
832
- // }>
833
- ```
834
-
835
- <a name='types-indexed'></a>
836
-
837
- ### Indexed Access Types
838
-
839
- TypeBox supports indexed access types with the Index function. This function enables uniform access to interior property and element types without having to extract them from the underlying schema representation. Index types are supported for Object, Array, Tuple, Union and Intersect types.
840
-
841
- ```typescript
842
- const T = Type.Object({ // type T = {
843
- x: Type.Number(), // x: number,
844
- y: Type.String(), // y: string,
845
- z: Type.Boolean() // z: boolean
846
- }) // }
847
-
848
- const A = Type.Index(T, ['x']) // type A = T['x']
849
- //
850
- // ... evaluated as
851
- //
852
- // const A: TNumber
853
-
854
- const B = Type.Index(T, ['x', 'y']) // type B = T['x' | 'y']
855
- //
856
- // ... evaluated as
857
- //
858
- // const B: TUnion<[
859
- // TNumber,
860
- // TString,
861
- // ]>
862
-
863
- const C = Type.Index(T, Type.KeyOf(T)) // type C = T[keyof T]
864
- //
865
- // ... evaluated as
866
- //
867
- // const C: TUnion<[
868
- // TNumber,
869
- // TString,
870
- // TBoolean
871
- // ]>
872
- ```
873
-
874
- <a name='types-mapped'></a>
875
-
876
- ### Mapped Types
877
-
878
- TypeBox supports mapped types with the Mapped function. This function accepts two arguments, the first is a union type typically derived from KeyOf, the second is a mapping function that receives a mapping key `K` that can be used to index properties of a type. The following implements a mapped type that remaps each property to be `T | null`.
879
-
880
- ```typescript
881
- const T = Type.Object({ // type T = {
882
- x: Type.Number(), // x: number,
883
- y: Type.String(), // y: string,
884
- z: Type.Boolean() // z: boolean
885
- }) // }
886
-
887
- const M = Type.Mapped(Type.KeyOf(T), K => { // type M = { [K in keyof T]: T[K] | null }
888
- return Type.Union([Type.Index(T, K), Type.Null()]) //
889
- }) // ... evaluated as
890
- //
891
- // const M: TObject<{
892
- // x: TUnion<[TNumber, TNull]>,
893
- // y: TUnion<[TString, TNull]>,
894
- // z: TUnion<[TBoolean, TNull]>
895
- // }>
896
- ```
897
-
898
- <a name='types-conditional'></a>
899
-
900
- ### Conditional Types
901
-
902
- TypeBox supports runtime conditional types with the Extends function. This function performs a structural assignability check against the first (`left`) and second (`right`) arguments and will return either the third (`true`) or fourth (`false`) argument based on the result. The conditional types Exclude and Extract are also supported. The following shows both TypeScript and TypeBox examples of conditional types.
903
-
904
- ```typescript
905
- // Extends
906
- const A = Type.Extends( // type A = string extends number ? 1 : 2
907
- Type.String(), //
908
- Type.Number(), // ... evaluated as
909
- Type.Literal(1), //
910
- Type.Literal(2) // const A: TLiteral<2>
911
- )
912
-
913
- // Extract
914
- const B = Type.Extract( // type B = Extract<1 | 2 | 3, 1>
915
- Type.Union([ //
916
- Type.Literal(1), // ... evaluated as
917
- Type.Literal(2), //
918
- Type.Literal(3) // const B: TLiteral<1>
919
- ]),
920
- Type.Literal(1)
921
- )
922
-
923
- // Exclude
924
- const C = Type.Exclude( // type C = Exclude<1 | 2 | 3, 1>
925
- Type.Union([ //
926
- Type.Literal(1), // ... evaluated as
927
- Type.Literal(2), //
928
- Type.Literal(3) // const C: TUnion<[
929
- ]), // TLiteral<2>,
930
- Type.Literal(1) // TLiteral<3>,
931
- ) // ]>
932
- ```
933
-
934
- <a name='types-transform'></a>
935
-
936
- ### Transform Types
937
-
938
- TypeBox supports value decoding and encoding with Transform types. These types work in tandem with the Encode and Decode functions available on the Value and TypeCompiler submodules. Transform types can be used to convert Json encoded values into constructs more natural to JavaScript. The following creates a Transform type to decode numbers into Dates using the Value submodule.
939
-
940
- ```typescript
941
- import { Value } from '@sinclair/typebox/value'
942
-
943
- const T = Type.Transform(Type.Number())
944
- .Decode(value => new Date(value)) // decode: number to Date
945
- .Encode(value => value.getTime()) // encode: Date to number
946
-
947
- const D = Value.Decode(T, 0) // const D = Date(1970-01-01T00:00:00.000Z)
948
- const E = Value.Encode(T, D) // const E = 0
949
- ```
950
- Use the StaticEncode or StaticDecode types to infer a Transform type.
951
- ```typescript
952
- import { Static, StaticDecode, StaticEncode } from '@sinclair/typebox'
953
-
954
- const T = Type.Transform(Type.Array(Type.Number(), { uniqueItems: true }))
955
- .Decode(value => new Set(value))
956
- .Encode(value => [...value])
957
-
958
- type D = StaticDecode<typeof T> // type D = Set<number>
959
- type E = StaticEncode<typeof T> // type E = Array<number>
960
- type T = Static<typeof T> // type T = Array<number>
961
- ```
962
-
963
- <a name='types-unsafe'></a>
964
-
965
- ### Unsafe Types
966
-
967
- TypeBox supports user defined types with Unsafe. This type allows you to specify both schema representation and inference type. The following creates an Unsafe type with a number schema that infers as string.
968
-
969
- ```typescript
970
- const T = Type.Unsafe<string>({ type: 'number' }) // const T = { type: 'number' }
971
-
972
- type T = Static<typeof T> // type T = string - ?
973
- ```
974
- The Unsafe type is often used to create schematics for extended specifications like OpenAPI.
975
- ```typescript
976
-
977
- const Nullable = <T extends TSchema>(schema: T) => Type.Unsafe<Static<T> | null>({
978
- ...schema, nullable: true
979
- })
980
-
981
- const T = Nullable(Type.String()) // const T = {
982
- // type: 'string',
983
- // nullable: true
984
- // }
985
-
986
- type T = Static<typeof T> // type T = string | null
987
-
988
- const StringEnum = <T extends string[]>(values: [...T]) => Type.Unsafe<T[number]>({
989
- type: 'string', enum: values
990
- })
991
- const S = StringEnum(['A', 'B', 'C']) // const S = {
992
- // enum: ['A', 'B', 'C']
993
- // }
994
-
995
- type S = Static<typeof T> // type S = 'A' | 'B' | 'C'
996
- ```
997
- <a name='types-guard'></a>
998
-
999
- ### TypeGuard
1000
-
1001
- TypeBox can check its own types with the TypeGuard module. This module is written for type introspection and provides structural tests for every built-in TypeBox type. Functions of this module return `is` guards which can be used with control flow assertions to obtain schema inference for unknown values. The following guards that the value `T` is TString.
1002
-
1003
- ```typescript
1004
- import { TypeGuard, Kind } from '@sinclair/typebox'
1005
-
1006
- const T = { [Kind]: 'String', type: 'string' }
1007
-
1008
- if(TypeGuard.IsString(T)) {
1009
-
1010
- // T is TString
1011
- }
1012
- ```
1013
-
1014
- <a name='values'></a>
1015
-
1016
- ## Values
1017
-
1018
- TypeBox provides an optional Value submodule that can be used to perform structural operations on JavaScript values. This submodule includes functionality to create, check and cast values from types as well as check equality, clone, diff and patch JavaScript values. This submodule is provided via optional import.
1019
-
1020
- ```typescript
1021
- import { Value } from '@sinclair/typebox/value'
1022
- ```
1023
-
1024
- <a name='values-assert'></a>
1025
-
1026
- ### Assert
1027
-
1028
- Use the Assert function to assert a value is valid.
1029
-
1030
- ```typescript
1031
- let value: unknown = 1
1032
-
1033
- Value.Assert(Type.Number(), value) // throws AssertError if invalid
1034
- ```
1035
-
1036
- <a name='values-create'></a>
1037
-
1038
- ### Create
1039
-
1040
- Use the Create function to create a value from a type. TypeBox will use default values if specified.
1041
-
1042
- ```typescript
1043
- const T = Type.Object({ x: Type.Number(), y: Type.Number({ default: 42 }) })
1044
-
1045
- const A = Value.Create(T) // const A = { x: 0, y: 42 }
1046
- ```
1047
-
1048
- <a name='values-clone'></a>
1049
-
1050
- ### Clone
1051
-
1052
- Use the Clone function to deeply clone a value.
1053
-
1054
- ```typescript
1055
- const A = Value.Clone({ x: 1, y: 2, z: 3 }) // const A = { x: 1, y: 2, z: 3 }
1056
- ```
1057
-
1058
- <a name='values-check'></a>
1059
-
1060
- ### Check
1061
-
1062
- Use the Check function to type check a value.
1063
-
1064
- ```typescript
1065
- const T = Type.Object({ x: Type.Number() })
1066
-
1067
- const R = Value.Check(T, { x: 1 }) // const R = true
1068
- ```
1069
-
1070
- <a name='values-convert'></a>
1071
-
1072
- ### Convert
1073
-
1074
- Use the Convert function to convert a value into its target type if a reasonable conversion is possible. This function may return an invalid value and should be checked before use. Its return type is `unknown`.
1075
-
1076
- ```typescript
1077
- const T = Type.Object({ x: Type.Number() })
1078
-
1079
- const R1 = Value.Convert(T, { x: '3.14' }) // const R1 = { x: 3.14 }
1080
-
1081
- const R2 = Value.Convert(T, { x: 'not a number' }) // const R2 = { x: 'not a number' }
1082
- ```
1083
-
1084
- <a name='values-clean'></a>
1085
-
1086
- ### Clean
1087
-
1088
- Use Clean to remove excess properties from a value. This function does not check the value and returns an unknown type. You should Check the result before use. Clean is a mutable operation. To avoid mutation, Clone the value first.
1089
-
1090
- ```typescript
1091
- const T = Type.Object({
1092
- x: Type.Number(),
1093
- y: Type.Number()
1094
- })
1095
-
1096
- const X = Value.Clean(T, null) // const 'X = null
1097
-
1098
- const Y = Value.Clean(T, { x: 1 }) // const 'Y = { x: 1 }
1099
-
1100
- const Z = Value.Clean(T, { x: 1, y: 2, z: 3 }) // const 'Z = { x: 1, y: 2 }
1101
- ```
1102
-
1103
- <a name='values-default'></a>
1104
-
1105
- ### Default
1106
-
1107
- Use Default to generate missing properties on a value using default schema annotations if available. This function does not check the value and returns an unknown type. You should Check the result before use. Default is a mutable operation. To avoid mutation, Clone the value first.
1108
-
1109
- ```typescript
1110
- const T = Type.Object({
1111
- x: Type.Number({ default: 0 }),
1112
- y: Type.Number({ default: 0 })
1113
- })
1114
-
1115
- const X = Value.Default(T, null) // const 'X = null - non-enumerable
1116
-
1117
- const Y = Value.Default(T, { }) // const 'Y = { x: 0, y: 0 }
1118
-
1119
- const Z = Value.Default(T, { x: 1 }) // const 'Z = { x: 1, y: 0 }
1120
- ```
1121
-
1122
- <a name='values-cast'></a>
1123
-
1124
- ### Cast
1125
-
1126
- Use the Cast function to upcast a value into a target type. This function will retain as much information as possible from the original value. The Cast function is intended to be used in data migration scenarios where existing values need to be upgraded to match a modified type.
1127
-
1128
- ```typescript
1129
- const T = Type.Object({ x: Type.Number(), y: Type.Number() }, { additionalProperties: false })
1130
-
1131
- const X = Value.Cast(T, null) // const X = { x: 0, y: 0 }
1132
-
1133
- const Y = Value.Cast(T, { x: 1 }) // const Y = { x: 1, y: 0 }
1134
-
1135
- const Z = Value.Cast(T, { x: 1, y: 2, z: 3 }) // const Z = { x: 1, y: 2 }
1136
- ```
1137
-
1138
- <a name='values-decode'></a>
1139
-
1140
- ### Decode
1141
-
1142
- Use the Decode function to decode a value from a type or throw if the value is invalid. The return value will infer as the decoded type. This function will run Transform codecs if available.
1143
-
1144
- ```typescript
1145
- const A = Value.Decode(Type.String(), 'hello') // const A = 'hello'
1146
-
1147
- const B = Value.Decode(Type.String(), 42) // throw
1148
- ```
1149
- <a name='values-decode'></a>
1150
-
1151
- ### Encode
1152
-
1153
- Use the Encode function to encode a value to a type or throw if the value is invalid. The return value will infer as the encoded type. This function will run Transform codecs if available.
1154
-
1155
- ```typescript
1156
- const A = Value.Encode(Type.String(), 'hello') // const A = 'hello'
1157
-
1158
- const B = Value.Encode(Type.String(), 42) // throw
1159
- ```
1160
-
1161
- <a name='values-parse'></a>
1162
-
1163
- ### Parse
1164
-
1165
- Use the Parse function to parse a value. This function calls the `Clone` `Clean`, `Default`, `Convert`, `Assert` and `Decode` Value functions in this exact order to process a value.
1166
-
1167
- ```typescript
1168
- const R = Value.Parse(Type.String(), 'hello') // const R: string = "hello"
1169
-
1170
- const E = Value.Parse(Type.String(), undefined) // throws AssertError
1171
- ```
1172
-
1173
- You can override the order in which functions are run, or omit functions entirely using the following.
1174
-
1175
- ```typescript
1176
- // Runs no functions.
1177
-
1178
- const R = Value.Parse([], Type.String(), 12345)
1179
-
1180
- // Runs the Assert() function.
1181
-
1182
- const E = Value.Parse(['Assert'], Type.String(), 12345)
1183
-
1184
- // Runs the Convert() function followed by the Assert() function.
1185
-
1186
- const S = Value.Parse(['Convert', 'Assert'], Type.String(), 12345)
1187
- ```
1188
-
1189
- <a name='values-equal'></a>
1190
-
1191
- ### Equal
1192
-
1193
- Use the Equal function to deeply check for value equality.
1194
-
1195
- ```typescript
1196
- const R = Value.Equal( // const R = true
1197
- { x: 1, y: 2, z: 3 },
1198
- { x: 1, y: 2, z: 3 }
1199
- )
1200
- ```
1201
-
1202
- <a name='values-hash'></a>
1203
-
1204
- ### Hash
1205
-
1206
- Use the Hash function to create a [FNV1A-64](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) non-cryptographic hash of a value.
1207
-
1208
- ```typescript
1209
- const A = Value.Hash({ x: 1, y: 2, z: 3 }) // const A = 2910466848807138541n
1210
-
1211
- const B = Value.Hash({ x: 1, y: 4, z: 3 }) // const B = 1418369778807423581n
1212
- ```
1213
-
1214
- <a name='values-diff'></a>
1215
-
1216
- ### Diff
1217
-
1218
- Use the Diff function to generate a sequence of edits that will transform one value into another.
1219
-
1220
- ```typescript
1221
- const E = Value.Diff( // const E = [
1222
- { x: 1, y: 2, z: 3 }, // { type: 'update', path: '/y', value: 4 },
1223
- { y: 4, z: 5, w: 6 } // { type: 'update', path: '/z', value: 5 },
1224
- ) // { type: 'insert', path: '/w', value: 6 },
1225
- // { type: 'delete', path: '/x' }
1226
- // ]
1227
- ```
1228
-
1229
- <a name='values-patch'></a>
1230
-
1231
- ### Patch
1232
-
1233
- Use the Patch function to apply a sequence of edits.
1234
-
1235
- ```typescript
1236
- const A = { x: 1, y: 2 }
1237
-
1238
- const B = { x: 3 }
1239
-
1240
- const E = Value.Diff(A, B) // const E = [
1241
- // { type: 'update', path: '/x', value: 3 },
1242
- // { type: 'delete', path: '/y' }
1243
- // ]
1244
-
1245
- const C = Value.Patch<typeof B>(A, E) // const C = { x: 3 }
1246
- ```
1247
-
1248
- <a name='values-errors'></a>
1249
-
1250
- ### Errors
1251
-
1252
- Use the Errors function to enumerate validation errors.
1253
-
1254
- ```typescript
1255
- const T = Type.Object({ x: Type.Number(), y: Type.Number() })
1256
-
1257
- const R = [...Value.Errors(T, { x: '42' })] // const R = [{
1258
- // schema: { type: 'number' },
1259
- // path: '/x',
1260
- // value: '42',
1261
- // message: 'Expected number'
1262
- // }, {
1263
- // schema: { type: 'number' },
1264
- // path: '/y',
1265
- // value: undefined,
1266
- // message: 'Expected number'
1267
- // }]
1268
- ```
1269
-
1270
- <a name='values-mutate'></a>
1271
-
1272
- ### Mutate
1273
-
1274
- Use the Mutate function to perform a deep mutable value assignment while retaining internal references.
1275
-
1276
- ```typescript
1277
- const Y = { z: 1 } // const Y = { z: 1 }
1278
- const X = { y: Y } // const X = { y: { z: 1 } }
1279
- const A = { x: X } // const A = { x: { y: { z: 1 } } }
1280
-
1281
- Value.Mutate(A, { x: { y: { z: 2 } } }) // A' = { x: { y: { z: 2 } } }
1282
-
1283
- const R0 = A.x.y.z === 2 // const R0 = true
1284
- const R1 = A.x.y === Y // const R1 = true
1285
- const R2 = A.x === X // const R2 = true
1286
- ```
1287
-
1288
- <a name='values-pointer'></a>
1289
-
1290
- ### Pointer
1291
-
1292
- Use ValuePointer to perform mutable updates on existing values using [RFC6901](https://www.rfc-editor.org/rfc/rfc6901) Json Pointers.
1293
-
1294
- ```typescript
1295
- import { ValuePointer } from '@sinclair/typebox/value'
1296
-
1297
- const A = { x: 0, y: 0, z: 0 }
1298
-
1299
- ValuePointer.Set(A, '/x', 1) // A' = { x: 1, y: 0, z: 0 }
1300
- ValuePointer.Set(A, '/y', 1) // A' = { x: 1, y: 1, z: 0 }
1301
- ValuePointer.Set(A, '/z', 1) // A' = { x: 1, y: 1, z: 1 }
1302
- ```
1303
-
1304
-
1305
-
1306
- <a name='syntax'></a>
1307
-
1308
- ## Syntax Types
1309
-
1310
- TypeBox provides experimental support for parsing TypeScript annotation syntax into TypeBox types.
1311
-
1312
- This feature is provided via optional import.
1313
-
1314
- ```typescript
1315
- import { Syntax } from '@sinclair/typebox/syntax'
1316
- ```
1317
-
1318
- <a name='syntax-create'></a>
1319
-
1320
- ### Create
1321
-
1322
- Use the Syntax function to create TypeBox types from TypeScript syntax ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgChQkWIhTYYwBgWKly1OoxZtO3foMkSGEdDXgAVOAF4Uo3AAoABkhwAuOOgCuIPjygAaOFR3Lx8-AkcASjgY2Jj2djhjUwt3cwB5PgArHgYYAB4ECTiS0rLyisrYhNi3OHMAOW9fAOKq9o7OuBqY4PqmsKg2rpHR+MT8AD4JCS5eeut5LEUGfLmeCCJ6ybHKmvWFmyLdk86euDrQlv9h07uy876rv1v7t-GCIA))
1323
-
1324
- ```typescript
1325
- const T = Syntax(`{ x: number, y: number }`) // const T: TObject<{
1326
- // x: TNumber,
1327
- // y: TNumber
1328
- // }>
1329
-
1330
- type T = Static<typeof T> // type T = {
1331
- // x: number,
1332
- // y: number
1333
- // }
1334
- ```
1335
-
1336
- <a name="syntax-parameters"></a>
1337
-
1338
- ### Parameters
1339
-
1340
- Syntax types can be parameterized to receive exterior types ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgCgJDCOhrwAKnAC8KUbgAUAAyQ4AXHHQBXEHx5QANHFQHjp8wS0BKOK7ev27ODLmKDCgHk+ACseBhgAHgQJd1i4+ITEpLdPN304BQA5EzNLGOSCwqK4VNcbDOz7KHzi2rqPL3wAPikfeRQVNUxNJCV8Ky0ABSxYYCwmCIUm52LUtvhkfyDQ8Kia+o2C0rh0wLAYYFlxycrcpot1zav47fK9g6OJrJzzFuv3m8amoA))
1341
-
1342
- ```typescript
1343
- const T = Syntax(`{ x: number, y: number }`) // const T: TObject<{
1344
- // x: TNumber,
1345
- // y: TNumber
1346
- // }>
1347
-
1348
- const S = Syntax({ T }, `Partial<T>`) // const S: TObject<{
1349
- // x: TOptional<TNumber>,
1350
- // y: TOptional<TNumber>
1351
- // }>
1352
- ```
1353
-
1354
-
1355
-
1356
- <a name="syntax-generics"></a>
1357
-
1358
- ### Generics
1359
-
1360
- Syntax types support generic parameters in the following way ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgChQkWIhTYYwBgWKly1OoxZtO3foMkSGEdDXgA1HgxjQ4AXhSjcACgAGAHgAaAGjgBNXwAtAD45CTg4HAAuOB84cLhUGID4iIAvGMD4-FcASgkjEzM4ACEsOhpLa2gae0dMFyQqmygCX1cEBOi4Zuh3AEZfAAZh4O8EpJ6rFvcRuEG4IbGEjKnqqFnh337lnPyJLl5S8uBK6Zq65AUld0OeCCJjit6oGlCIiPZ2ODun05fag5Oh8QaCweCIZCoV8Pt0kN0FpM5qshm0ElCMZisSCYRFJvCYnNJgsUWjseSKeDcXBVgTFr4kb5Vv0COjKezsTD8EA))
1361
-
1362
- ```typescript
1363
- const Vector = Syntax(`<X, Y, Z> {
1364
- x: X,
1365
- y: Y,
1366
- z: Z
1367
- }`)
1368
-
1369
- const BasisVectors = Syntax({ Vector }, `{
1370
- x: Vector<1, 0, 0>,
1371
- y: Vector<0, 1, 0>,
1372
- z: Vector<0, 0, 1>,
1373
- }`)
1374
-
1375
- type BasisVectors = Static<typeof BasisVectors> // type BasisVectors = {
1376
- // x: { x: 1, y: 0, z: 0 },
1377
- // y: { x: 0, y: 1, z: 0 },
1378
- // z: { x: 0, y: 0, z: 1 }
1379
- // }
1380
- ```
1381
-
1382
- <a name='syntax-options'></a>
1383
-
1384
- ### Options
1385
-
1386
- Options can be passed via the last parameter.
1387
-
1388
- ```typescript
1389
- const T = Syntax(`number`, { minimum: 42 }) // const T = {
1390
- // type: 'number',
1391
- // minimum: 42
1392
- // }
1393
- ```
1394
-
1395
- <a name='syntax-no-infer'></a>
1396
-
1397
- ### NoInfer
1398
-
1399
- Syntax parsing is an expensive type level operation and can impact on language service performance. Use the NoInfer function parse syntax at runtime only.
1400
-
1401
- ```typescript
1402
- import { NoInfer } from '@sinclair/typebox/syntax'
1403
-
1404
- const T = NoInfer(`number | string`) // const T: TSchema = {
1405
- // anyOf: [
1406
- // { type: 'number' },
1407
- // { type: 'string' }
1408
- // ]
1409
- // }
1410
- ```
1411
-
1412
- <a name='typeregistry'></a>
1413
-
1414
- ## TypeRegistry
1415
-
1416
- The TypeBox type system can be extended with additional types and formats using the TypeRegistry and FormatRegistry modules. These modules integrate deeply with TypeBox's internal type checking infrastructure and can be used to create application specific types, or register schematics for alternative specifications.
1417
-
1418
- <a name='typeregistry-type'></a>
1419
-
1420
- ### TypeRegistry
1421
-
1422
- Use the TypeRegistry to register a type. The Kind must match the registered type name.
1423
-
1424
- ```typescript
1425
- import { TSchema, Kind, TypeRegistry } from '@sinclair/typebox'
1426
-
1427
- TypeRegistry.Set('Foo', (schema, value) => value === 'foo')
1428
-
1429
- const Foo = { [Kind]: 'Foo' } as TSchema
1430
-
1431
- const A = Value.Check(Foo, 'foo') // const A = true
1432
-
1433
- const B = Value.Check(Foo, 'bar') // const B = false
1434
- ```
1435
-
1436
- <a name='typeregistry-format'></a>
1437
-
1438
- ### FormatRegistry
1439
-
1440
- Use the FormatRegistry to register a string format.
1441
-
1442
- ```typescript
1443
- import { FormatRegistry } from '@sinclair/typebox'
1444
-
1445
- FormatRegistry.Set('foo', (value) => value === 'foo')
1446
-
1447
- const T = Type.String({ format: 'foo' })
1448
-
1449
- const A = Value.Check(T, 'foo') // const A = true
1450
-
1451
- const B = Value.Check(T, 'bar') // const B = false
1452
- ```
1453
-
1454
- <a name='typecheck'></a>
1455
-
1456
- ## TypeCheck
1457
-
1458
- TypeBox types target Json Schema Draft 7 and are compatible with any validator that supports this specification. TypeBox also provides a built-in type checking compiler designed specifically for TypeBox types that offers high performance compilation and value checking.
1459
-
1460
- The following sections detail using Ajv and the TypeBox compiler infrastructure.
1461
-
1462
- <a name='typecheck-ajv'></a>
1463
-
1464
- ## Ajv
1465
-
1466
- The following shows the recommended setup for Ajv.
1467
-
1468
- ```bash
1469
- $ npm install ajv ajv-formats --save
1470
- ```
1471
-
1472
- ```typescript
1473
- import { Type } from '@sinclair/typebox'
1474
- import addFormats from 'ajv-formats'
1475
- import Ajv from 'ajv'
1476
-
1477
- const ajv = addFormats(new Ajv({}), [
1478
- 'date-time',
1479
- 'time',
1480
- 'date',
1481
- 'email',
1482
- 'hostname',
1483
- 'ipv4',
1484
- 'ipv6',
1485
- 'uri',
1486
- 'uri-reference',
1487
- 'uuid',
1488
- 'uri-template',
1489
- 'json-pointer',
1490
- 'relative-json-pointer',
1491
- 'regex'
1492
- ])
1493
-
1494
- const validate = ajv.compile(Type.Object({
1495
- x: Type.Number(),
1496
- y: Type.Number(),
1497
- z: Type.Number()
1498
- }))
1499
-
1500
- const R = validate({ x: 1, y: 2, z: 3 }) // const R = true
1501
- ```
1502
-
1503
- <a name='typecheck-typecompiler'></a>
1504
-
1505
- ### TypeCompiler
1506
-
1507
- The TypeBox TypeCompiler is a high performance JIT validation compiler that transforms TypeBox types into optimized JavaScript validation routines. The compiler is tuned for fast compilation as well as fast value assertion. It is built to serve as a validation backend that can be integrated into larger applications. It can also be used for code generation.
1508
-
1509
- The TypeCompiler is provided as an optional import.
1510
-
1511
- ```typescript
1512
- import { TypeCompiler } from '@sinclair/typebox/compiler'
1513
- ```
1514
-
1515
- Use the Compile function to JIT compile a type. Note that compilation is generally an expensive operation and should only be performed once per type during application start up. TypeBox does not cache previously compiled types, and applications are expected to hold references to each compiled type for the lifetime of the application.
1516
-
1517
- ```typescript
1518
- const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck<TObject<{
1519
- x: Type.Number(), // x: TNumber;
1520
- y: Type.Number(), // y: TNumber;
1521
- z: Type.Number() // z: TNumber;
1522
- })) // }>>
1523
-
1524
- const R = C.Check({ x: 1, y: 2, z: 3 }) // const R = true
1525
- ```
1526
-
1527
- Use the Errors function to generate diagnostic errors for a value. The Errors function will return an iterator that when enumerated; will perform an exhaustive check across the entire value yielding any error found. For performance, this function should only be called after a failed Check. Applications may also choose to yield only the first value to avoid exhaustive error generation.
1528
-
1529
- ```typescript
1530
- const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck<TObject<{
1531
- x: Type.Number(), // x: TNumber;
1532
- y: Type.Number(), // y: TNumber;
1533
- z: Type.Number() // z: TNumber;
1534
- })) // }>>
1535
-
1536
- const value = { }
1537
-
1538
- const first = C.Errors(value).First() // const first = {
1539
- // schema: { type: 'number' },
1540
- // path: '/x',
1541
- // value: undefined,
1542
- // message: 'Expected number'
1543
- // }
1544
-
1545
- const all = [...C.Errors(value)] // const all = [{
1546
- // schema: { type: 'number' },
1547
- // path: '/x',
1548
- // value: undefined,
1549
- // message: 'Expected number'
1550
- // }, {
1551
- // schema: { type: 'number' },
1552
- // path: '/y',
1553
- // value: undefined,
1554
- // message: 'Expected number'
1555
- // }, {
1556
- // schema: { type: 'number' },
1557
- // path: '/z',
1558
- // value: undefined,
1559
- // message: 'Expected number'
1560
- // }]
1561
- ```
1562
-
1563
- Use the Code function to generate assertion functions as strings. This function can be used to generate code that can be written to disk as importable modules. This technique is sometimes referred to as Ahead of Time (AOT) compilation. The following generates code to check a string.
1564
-
1565
- ```typescript
1566
- const C = TypeCompiler.Code(Type.String()) // const C = `return function check(value) {
1567
- // return (
1568
- // (typeof value === 'string')
1569
- // )
1570
- // }`
1571
- ```
1572
-
1573
- <a name='typemap'></a>
1574
-
1575
- ## TypeMap
1576
-
1577
- TypeBox offers an external package for bidirectional mapping between TypeBox, Valibot, and Zod type libraries. It also includes syntax parsing support for Valibot and Zod and supports the Standard Schema specification. For more details on TypeMap, refer to the project repository.
1578
-
1579
- [TypeMap Repository](https://github.com/sinclairzx81/typemap)
1580
-
1581
- <a name='typemap-usage'></a>
1582
-
1583
- ### Usage
1584
-
1585
- TypeMap needs to be installed separately
1586
-
1587
- ```bash
1588
- $ npm install @sinclair/typemap
1589
- ```
1590
-
1591
- Once installed it offers advanced structural remapping between various runtime type libraries ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgFQJ5gKYCEIA8A0cAyqgHYwCGBcAWhACZwC+cAZlBCHAOQACAzsFIBjADYVgUAPQx0GEBTDcAUMuERS-eMjgBeFHJy4AFAAMkuAFxxSAVxAAjDFEKprdx88IAvd-adQzKYAlHBwUlJw6pra1sgA8g4AVhjCMAA8CMphObl5+QWFRcW5ETlWKABy-s4A3NkljU3NBWVhblU1UPUtvX3FbXC+nZ7dDf0TE2VMAHyq0VrEesRklCbIoS1lC-BE1twWfqOuRwE+p87MKmoaiwBKy3T0xkTBAHRgFFD8GMZ2oqJNnltrd4HdrFlJltImEKh4Aj0oU1Bh14XVxkiBjChhcxpjGtMwkA))
1592
-
1593
- ```typescript
1594
- import { TypeBox, Syntax, Zod } from '@sinclair/typemap'
1595
-
1596
- const T = TypeBox(`{ x: number, y: number, z: number }`) // const T: TObject<{
1597
- // x: TNumber;
1598
- // y: TNumber;
1599
- // z: TNumber;
1600
- // }>
1601
-
1602
- const S = Syntax(T) // const S: '{ x: number, y: number, z: number }'
1603
-
1604
- const R = Zod(S).parse(null) // const R: {
1605
- // x: number;
1606
- // y: number;
1607
- // z: number;
1608
- // }
1609
- ```
1610
-
1611
- <a name='typesystem'></a>
1612
-
1613
- ## TypeSystem
1614
-
1615
- The TypeBox TypeSystem module provides configurations to use either Json Schema or TypeScript type checking semantics. Configurations made to the TypeSystem module are observed by the TypeCompiler, Value and Error modules.
1616
-
1617
- <a name='typesystem-policies'></a>
1618
-
1619
- ### Policies
1620
-
1621
- TypeBox validates using standard Json Schema assertion policies by default. The TypeSystemPolicy module can override some of these to have TypeBox assert values inline with TypeScript static checks. It also provides overrides for certain checking rules related to non-serializable values (such as void) which can be helpful in Json based protocols such as Json Rpc 2.0.
1622
-
1623
- The following overrides are available.
1624
-
1625
- ```typescript
1626
- import { TypeSystemPolicy } from '@sinclair/typebox/system'
1627
-
1628
- // Disallow undefined values for optional properties (default is false)
1629
- //
1630
- // const A: { x?: number } = { x: undefined } - disallowed when enabled
1631
-
1632
- TypeSystemPolicy.ExactOptionalPropertyTypes = true
1633
-
1634
- // Allow arrays to validate as object types (default is false)
1635
- //
1636
- // const A: {} = [] - allowed in TS
1637
-
1638
- TypeSystemPolicy.AllowArrayObject = true
1639
-
1640
- // Allow numeric values to be NaN or + or - Infinity (default is false)
1641
- //
1642
- // const A: number = NaN - allowed in TS
1643
-
1644
- TypeSystemPolicy.AllowNaN = true
1645
-
1646
- // Allow void types to check with undefined and null (default is false)
1647
- //
1648
- // Used to signal void return on Json-Rpc 2.0 protocol
1649
-
1650
- TypeSystemPolicy.AllowNullVoid = true
1651
- ```
1652
-
1653
- <a name='error-function'></a>
1654
-
1655
- ## Error Function
1656
-
1657
- Error messages in TypeBox can be customized by defining an ErrorFunction. This function allows for the localization of error messages as well as enabling custom error messages for custom types. By default, TypeBox will generate messages using the `en-US` locale. To support additional locales, you can replicate the function found in `src/errors/function.ts` and create a locale specific translation. The function can then be set via SetErrorFunction.
1658
-
1659
- The following example shows an inline error function that intercepts errors for String, Number and Boolean only. The DefaultErrorFunction is used to return a default error message.
1660
-
1661
-
1662
- ```typescript
1663
- import { SetErrorFunction, DefaultErrorFunction, ValueErrorType } from '@sinclair/typebox/errors'
1664
-
1665
- SetErrorFunction((error) => { // i18n override
1666
- switch(error.errorType) {
1667
- /* en-US */ case ValueErrorType.String: return 'Expected string'
1668
- /* fr-FR */ case ValueErrorType.Number: return 'Nombre attendu'
1669
- /* ko-KR */ case ValueErrorType.Boolean: return '예상 부울'
1670
- /* en-US */ default: return DefaultErrorFunction(error)
1671
- }
1672
- })
1673
- const T = Type.Object({ // const T: TObject<{
1674
- x: Type.String(), // TString,
1675
- y: Type.Number(), // TNumber,
1676
- z: Type.Boolean() // TBoolean
1677
- }) // }>
1678
-
1679
- const E = [...Value.Errors(T, { // const E = [{
1680
- x: null, // type: 48,
1681
- y: null, // schema: { ... },
1682
- z: null // path: '/x',
1683
- })] // value: null,
1684
- // message: 'Expected string'
1685
- // }, {
1686
- // type: 34,
1687
- // schema: { ... },
1688
- // path: '/y',
1689
- // value: null,
1690
- // message: 'Nombre attendu'
1691
- // }, {
1692
- // type: 14,
1693
- // schema: { ... },
1694
- // path: '/z',
1695
- // value: null,
1696
- // message: '예상 부울'
1697
- // }]
1698
- ```
1699
-
1700
- <a name='workbench'></a>
1701
-
1702
- ## TypeBox Workbench
1703
-
1704
- TypeBox offers a web based code generation tool that can convert TypeScript types into TypeBox types as well as several other ecosystem libraries.
1705
-
1706
- [TypeBox Workbench Link Here](https://sinclairzx81.github.io/typebox-workbench/)
1707
-
1708
- <a name='codegen'></a>
1709
-
1710
- ## TypeBox Codegen
1711
-
1712
- TypeBox provides a code generation library that can be integrated into toolchains to automate type translation between TypeScript and TypeBox. This library also includes functionality to transform TypeScript types to other ecosystem libraries.
1713
-
1714
- [TypeBox Codegen Link Here](https://github.com/sinclairzx81/typebox-codegen)
1715
-
1716
- <a name='ecosystem'></a>
1717
-
1718
- ## Ecosystem
1719
-
1720
- The following is a list of community packages that offer general tooling, extended functionality and framework integration support for TypeBox.
1721
-
1722
- | Package | Description |
1723
- | ------------- | ------------- |
1724
- | [drizzle-typebox](https://www.npmjs.com/package/drizzle-typebox) | Generates TypeBox types from Drizzle ORM schemas |
1725
- | [elysia](https://github.com/elysiajs/elysia) | Fast and friendly Bun web framework |
1726
- | [fastify-type-provider-typebox](https://github.com/fastify/fastify-type-provider-typebox) | Fastify TypeBox integration with the Fastify Type Provider |
1727
- | [feathersjs](https://github.com/feathersjs/feathers) | The API and real-time application framework |
1728
- | [fetch-typebox](https://github.com/erfanium/fetch-typebox) | Drop-in replacement for fetch that brings easy integration with TypeBox |
1729
- | [@lonli-lokli/fetcher-typebox](https://github.com/Lonli-Lokli/fetcher-ts/tree/master/packages/fetcher-typebox) | A strongly-typed fetch wrapper for TypeScript applications with optional runtime validation using TypeBox |
1730
- | [h3-typebox](https://github.com/kevinmarrec/h3-typebox) | Schema validation utilities for h3 using TypeBox & Ajv |
1731
- | [http-wizard](https://github.com/flodlc/http-wizard) | Type safe http client library for Fastify |
1732
- | [json2typebox](https://github.com/hacxy/json2typebox) | Creating TypeBox code from Json Data |
1733
- | [nominal-typebox](https://github.com/Coder-Spirit/nominal/tree/main/%40coderspirit/nominal-typebox) | Allows devs to integrate nominal types into TypeBox schemas |
1734
- | [openapi-box](https://github.com/geut/openapi-box) | Generate TypeBox types from OpenApi IDL + Http client library |
1735
- | [prismabox](https://github.com/m1212e/prismabox) | Converts a prisma.schema to TypeBox schema matching the database models |
1736
- | [schema2typebox](https://github.com/xddq/schema2typebox) | Creating TypeBox code from Json Schemas |
1737
- | [sveltekit-superforms](https://github.com/ciscoheat/sveltekit-superforms) | A comprehensive SvelteKit form library for server and client validation |
1738
- | [ts2typebox](https://github.com/xddq/ts2typebox) | Creating TypeBox code from Typescript types |
1739
- | [typebox-cli](https://github.com/gsuess/typebox-cli) | Generate Schema with TypeBox from the CLI |
1740
- | [typebox-form-parser](https://github.com/jtlapp/typebox-form-parser) | Parses form and query data based on TypeBox schemas |
1741
- | [typebox-schema-faker](https://github.com/iam-medvedev/typebox-schema-faker) | Generate fake data from TypeBox schemas for testing, prototyping and development |
1742
-
1743
-
1744
- <a name='benchmark'></a>
1745
-
1746
- ## Benchmark
1747
-
1748
- This project maintains a set of benchmarks that measure Ajv, Value and TypeCompiler compilation and validation performance. These benchmarks can be run locally by cloning this repository and running `npm run benchmark`. The results below show for Ajv version 8.12.0 running on Node 20.10.0.
1749
-
1750
- For additional comparative benchmarks, please refer to [typescript-runtime-type-benchmarks](https://moltar.github.io/typescript-runtime-type-benchmarks/).
1751
-
1752
- <a name='benchmark-compile'></a>
1753
-
1754
- ### Compile
1755
-
1756
- This benchmark measures compilation performance for varying types.
1757
-
1758
- ```typescript
1759
- ┌────────────────────────────┬────────────┬──────────────┬──────────────┬──────────────┐
1760
- │ (index) │ Iterations │ Ajv │ TypeCompiler │ Performance │
1761
- ├────────────────────────────┼────────────┼──────────────┼──────────────┼──────────────┤
1762
- Literal_String 1000 ' 211 ms' ' 8 ms' ' 26.38 x'
1763
- │ Literal_Number │ 1000 │ ' 185 ms' │ ' 5 ms' │ ' 37.00 x' │
1764
- Literal_Boolean │ 1000 │ ' 195 ms' │ ' 4 ms' │ ' 48.75 x' │
1765
- Primitive_Number │ 1000 │ ' 149 ms' │ ' 7 ms' │ ' 21.29 x' │
1766
- Primitive_String │ 1000 │ ' 135 ms' │ ' 5 ms' │ ' 27.00 x' │
1767
- Primitive_String_Pattern │ 1000 │ ' 193 ms' │ ' 10 ms' │ ' 19.30 x' │
1768
- Primitive_Boolean │ 1000 │ ' 152 ms' │ ' 4 ms' │ ' 38.00 x' │
1769
- Primitive_Null │ 1000 │ ' 147 ms' │ ' 4 ms' │ ' 36.75 x' │
1770
- Object_Unconstrained │ 1000 │ ' 1065 ms' │ ' 26 ms' │ ' 40.96 x' │
1771
- Object_Constrained │ 1000 │ ' 1183 ms' │ ' 26 ms' │ ' 45.50 x' │
1772
- Object_Vector3 │ 1000 │ ' 407 ms' │ ' 9 ms' │ ' 45.22 x' │
1773
- Object_Box3D │ 1000 │ ' 1777 ms' │ ' 24 ms' │ ' 74.04 x' │
1774
- Tuple_Primitive │ 1000 │ ' 485 ms' │ ' 11 ms' │ ' 44.09 x' │
1775
- Tuple_Object │ 1000 │ ' 1344 ms' │ ' 17 ms' │ ' 79.06 x' │
1776
- Composite_Intersect │ 1000 │ ' 606 ms' │ ' 14 ms' │ ' 43.29 x' │
1777
- Composite_Union │ 1000 │ ' 522 ms' │ ' 17 ms' │ ' 30.71 x' │
1778
- Math_Vector4 │ 1000 │ ' 851 ms' │ ' 9 ms' │ ' 94.56 x' │
1779
- Math_Matrix4 │ 1000 │ ' 406 ms' │ ' 10 ms' │ ' 40.60 x' │
1780
- Array_Primitive_Number │ 1000 │ ' 367 ms' │ ' 6 ms' │ ' 61.17 x' │
1781
- Array_Primitive_String │ 1000 │ ' 339 ms' │ ' 7 ms' │ ' 48.43 x' │
1782
- Array_Primitive_Boolean │ 1000 │ ' 325 ms' │ ' 5 ms' │ ' 65.00 x' │
1783
- Array_Object_Unconstrained │ 1000 │ ' 1863 ms' │ ' 21 ms' │ ' 88.71 x' │
1784
- Array_Object_Constrained │ 1000 │ ' 1535 ms' │ ' 18 ms' │ ' 85.28 x' │
1785
- Array_Tuple_Primitive │ 1000 │ ' 829 ms' │ ' 14 ms' │ ' 59.21 x' │
1786
- Array_Tuple_Object │ 1000 │ ' 1674 ms' │ ' 14 ms' │ ' 119.57 x' │
1787
- Array_Composite_Intersect │ 1000 │ ' 789 ms' │ ' 13 ms' │ ' 60.69 x' │
1788
- Array_Composite_Union │ 1000 │ ' 822 ms' │ ' 15 ms' │ ' 54.80 x' │
1789
- Array_Math_Vector4 │ 1000 │ ' 1129 ms' │ ' 14 ms' │ ' 80.64 x' │
1790
- Array_Math_Matrix4 │ 1000 │ ' 673 ms' │ ' 9 ms' │ ' 74.78 x' │
1791
- └────────────────────────────┴────────────┴──────────────┴──────────────┴──────────────┘
1792
- ```
1793
-
1794
- <a name='benchmark-validate'></a>
1795
-
1796
- ### Validate
1797
-
1798
- This benchmark measures validation performance for varying types.
1799
-
1800
- ```typescript
1801
- ┌────────────────────────────┬────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
1802
- │ (index) │ Iterations │ ValueCheck │ Ajv │ TypeCompiler │ Performance │
1803
- ├────────────────────────────┼────────────┼──────────────┼──────────────┼──────────────┼──────────────┤
1804
- Literal_String 1000000 ' 17 ms' ' 5 ms' ' 5 ms' ' 1.00 x'
1805
- │ Literal_Number │ 1000000 │ ' 14 ms' │ ' 18 ms' │ ' 9 ms' │ ' 2.00 x' │
1806
- Literal_Boolean │ 1000000 │ ' 14 ms' │ ' 20 ms' │ ' 9 ms' │ ' 2.22 x' │
1807
- Primitive_Number │ 1000000 │ ' 17 ms' │ ' 19 ms' │ ' 9 ms' │ ' 2.11 x' │
1808
- Primitive_String │ 1000000 │ ' 17 ms' │ ' 18 ms' │ ' 10 ms' │ ' 1.80 x' │
1809
- Primitive_String_Pattern │ 1000000 │ ' 172 ms' │ ' 46 ms' │ ' 41 ms' │ ' 1.12 x' │
1810
- Primitive_Boolean │ 1000000 │ ' 14 ms' │ ' 19 ms' │ ' 10 ms' │ ' 1.90 x' │
1811
- Primitive_Null │ 1000000 │ ' 16 ms' │ ' 19 ms' │ ' 9 ms' │ ' 2.11 x' │
1812
- Object_Unconstrained │ 1000000 │ ' 437 ms' │ ' 28 ms' │ ' 14 ms' │ ' 2.00 x' │
1813
- Object_Constrained │ 1000000 │ ' 653 ms' │ ' 46 ms' │ ' 37 ms' │ ' 1.24 x' │
1814
- Object_Vector3 │ 1000000 │ ' 201 ms' │ ' 22 ms' │ ' 12 ms' │ ' 1.83 x' │
1815
- Object_Box3D │ 1000000 │ ' 961 ms' │ ' 37 ms' │ ' 19 ms' │ ' 1.95 x' │
1816
- Object_Recursive │ 1000000 │ ' 3715 ms' │ ' 363 ms' │ ' 174 ms' │ ' 2.09 x' │
1817
- Tuple_Primitive │ 1000000 │ ' 107 ms' │ ' 23 ms' │ ' 11 ms' │ ' 2.09 x' │
1818
- Tuple_Object │ 1000000 │ ' 375 ms' │ ' 28 ms' │ ' 15 ms' │ ' 1.87 x' │
1819
- Composite_Intersect │ 1000000 │ ' 377 ms' │ ' 22 ms' │ ' 12 ms' │ ' 1.83 x' │
1820
- Composite_Union │ 1000000 │ ' 337 ms' │ ' 30 ms' │ ' 17 ms' │ ' 1.76 x' │
1821
- Math_Vector4 │ 1000000 │ ' 137 ms' │ ' 23 ms' │ ' 11 ms' │ ' 2.09 x' │
1822
- Math_Matrix4 │ 1000000 │ ' 576 ms' │ ' 37 ms' │ ' 28 ms' │ ' 1.32 x' │
1823
- Array_Primitive_Number │ 1000000 │ ' 145 ms' │ ' 23 ms' │ ' 12 ms' │ ' 1.92 x' │
1824
- Array_Primitive_String │ 1000000 │ ' 152 ms' │ ' 22 ms' │ ' 13 ms' │ ' 1.69 x' │
1825
- Array_Primitive_Boolean │ 1000000 │ ' 131 ms' │ ' 20 ms' │ ' 13 ms' │ ' 1.54 x' │
1826
- Array_Object_Unconstrained │ 1000000 │ ' 2821 ms' │ ' 62 ms' │ ' 45 ms' │ ' 1.38 x' │
1827
- Array_Object_Constrained │ 1000000 │ ' 2958 ms' │ ' 119 ms' │ ' 134 ms' │ ' 0.89 x' │
1828
- Array_Object_Recursive │ 1000000 │ ' 14695 ms' │ ' 1621 ms' │ ' 635 ms' │ ' 2.55 x' │
1829
- Array_Tuple_Primitive │ 1000000 │ ' 478 ms' │ ' 35 ms' │ ' 28 ms' │ ' 1.25 x' │
1830
- Array_Tuple_Object │ 1000000 │ ' 1623 ms' │ ' 63 ms' │ ' 48 ms' │ ' 1.31 x' │
1831
- Array_Composite_Intersect │ 1000000 │ ' 1582 ms' │ ' 43 ms' │ ' 30 ms' │ ' 1.43 x' │
1832
- Array_Composite_Union │ 1000000 │ ' 1331 ms' │ ' 76 ms' │ ' 40 ms' │ ' 1.90 x' │
1833
- Array_Math_Vector4 │ 1000000 │ ' 564 ms' │ ' 38 ms' │ ' 24 ms' │ ' 1.58 x' │
1834
- Array_Math_Matrix4 │ 1000000 │ ' 2382 ms' │ ' 111 ms' │ ' 83 ms' │ ' 1.34 x' │
1835
- └────────────────────────────┴────────────┴──────────────┴──────────────┴──────────────┴──────────────┘
1836
- ```
1837
-
1838
- <a name='benchmark-compression'></a>
1839
-
1840
- ### Compression
1841
-
1842
- The following table lists esbuild compiled and minified sizes for each TypeBox module.
1843
-
1844
- ```typescript
1845
- ┌──────────────────────┬────────────┬────────────┬─────────────┐
1846
- │ (index) │ Compiled │ Minified │ Compression │
1847
- ├──────────────────────┼────────────┼────────────┼─────────────┤
1848
- typebox/compiler '122.4 kb' ' 53.4 kb' '2.29 x'
1849
- │ typebox/errors │ ' 67.6 kb' │ ' 29.6 kb' │ '2.28 x' │
1850
- │ typebox/syntax │ '132.9 kb' │ ' 54.2 kb' │ '2.45 x' │
1851
- │ typebox/system │ ' 7.4 kb' │ ' 3.2 kb' │ '2.33 x' │
1852
- │ typebox/value │ '150.1 kb' │ ' 62.2 kb' │ '2.41 x' │
1853
- │ typebox │ '106.8 kb' │ ' 43.2 kb' │ '2.47 x' │
1854
- └──────────────────────┴────────────┴────────────┴─────────────┘
1855
- ```
1856
-
1857
- <a name='contribute'></a>
1858
-
1859
- ## Contribute
1860
-
1861
- TypeBox is open to community contribution. Please ensure you submit an open issue before submitting your pull request. The TypeBox project prefers open community discussion before accepting new features.
1
+ <div align='center'>
2
+
3
+ <h1>TypeBox Legacy</h1>
4
+
5
+ <p>Json Schema Type Builder with Static Type Resolution for TypeScript</p>
6
+
7
+ <img src="https://raw.githubusercontent.com/sinclairzx81/typebox/refs/heads/master/typebox.png" />
8
+
9
+ <br />
10
+ <br />
11
+
12
+ [![npm version](https://badge.fury.io/js/%40sinclair%2Ftypebox.svg)](https://badge.fury.io/js/%40sinclair%2Ftypebox)
13
+ [![Downloads](https://img.shields.io/npm/dm/%40sinclair%2Ftypebox.svg)](https://www.npmjs.com/package/%40sinclair%2Ftypebox)
14
+ [![Build](https://github.com/sinclairzx81/typebox/actions/workflows/build.yml/badge.svg)](https://github.com/sinclairzx81/typebox/actions/workflows/build.yml)
15
+ [![License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
16
+
17
+ </div>
18
+
19
+ <a name="Install"></a>
20
+
21
+ ## Install
22
+
23
+ ```bash
24
+ $ npm install @sinclair/typebox --save
25
+ ```
26
+
27
+ ## Example
28
+
29
+ ```typescript
30
+ import { Type, type Static } from '@sinclair/typebox'
31
+
32
+ const T = Type.Object({ // const T = {
33
+ x: Type.Number(), // type: 'object',
34
+ y: Type.Number(), // required: ['x', 'y', 'z'],
35
+ z: Type.Number() // properties: {
36
+ }) // x: { type: 'number' },
37
+ // y: { type: 'number' },
38
+ // z: { type: 'number' }
39
+ // }
40
+ // }
41
+
42
+ type T = Static<typeof T> // type T = {
43
+ // x: number,
44
+ // y: number,
45
+ // z: number
46
+ // }
47
+ ```
48
+
49
+
50
+ <a name="Overview"></a>
51
+
52
+ ## Overview
53
+
54
+ > ⚠️ TypeBox versions (pre-1.0) continue active maintenance through 2026 and beyond. This repository services as the OIDC publishing environment for the `@sinclair/typebox` package scope on NPM. For TypeBox versions 1.0 and above, refer to https://github.com/sinclairzx81/typebox
55
+
56
+ TypeBox is a runtime type builder that creates in-memory Json Schema objects that infer as TypeScript types. The schematics produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox offers a unified type that can be statically checked by TypeScript and runtime asserted using standard Json Schema validation.
57
+
58
+ This library is designed to allow Json Schema to compose similar to how types compose within TypeScript's type system. It can be used as a simple tool to build up complex schematics or integrated into REST and RPC services to help validate data received over the wire.
59
+
60
+ License MIT
61
+
62
+ ## Contents
63
+ - [Install](#install)
64
+ - [Overview](#overview)
65
+ - [Usage](#usage)
66
+ - [Types](#types)
67
+ - [Json](#types-json)
68
+ - [JavaScript](#types-javascript)
69
+ - [Options](#types-options)
70
+ - [Properties](#types-properties)
71
+ - [Generics](#types-generics)
72
+ - [Recursive](#types-recursive)
73
+ - [Modules](#types-modules)
74
+ - [Template Literal](#types-template-literal)
75
+ - [Indexed](#types-indexed)
76
+ - [Mapped](#types-mapped)
77
+ - [Conditional](#types-conditional)
78
+ - [Transform](#types-transform)
79
+ - [Guard](#types-guard)
80
+ - [Unsafe](#types-unsafe)
81
+ - [Values](#values)
82
+ - [Assert](#values-assert)
83
+ - [Create](#values-create)
84
+ - [Clone](#values-clone)
85
+ - [Check](#values-check)
86
+ - [Convert](#values-convert)
87
+ - [Default](#values-default)
88
+ - [Clean](#values-clean)
89
+ - [Cast](#values-cast)
90
+ - [Decode](#values-decode)
91
+ - [Encode](#values-decode)
92
+ - [Parse](#values-parse)
93
+ - [Equal](#values-equal)
94
+ - [Hash](#values-hash)
95
+ - [Diff](#values-diff)
96
+ - [Patch](#values-patch)
97
+ - [Errors](#values-errors)
98
+ - [Mutate](#values-mutate)
99
+ - [Pointer](#values-pointer)
100
+ - [Syntax](#syntax)
101
+ - [Create](#syntax-create)
102
+ - [Parameters](#syntax-parameters)
103
+ - [Generics](#syntax-generics)
104
+ - [Options](#syntax-options)
105
+ - [NoInfer](#syntax-no-infer)
106
+ - [TypeRegistry](#typeregistry)
107
+ - [Type](#typeregistry-type)
108
+ - [Format](#typeregistry-format)
109
+ - [TypeCheck](#typecheck)
110
+ - [Ajv](#typecheck-ajv)
111
+ - [TypeCompiler](#typecheck-typecompiler)
112
+ - [TypeMap](#typemap)
113
+ - [Usage](#typemap-usage)
114
+ - [TypeSystem](#typesystem)
115
+ - [Policies](#typesystem-policies)
116
+ - [Error Function](#error-function)
117
+ - [Workbench](#workbench)
118
+ - [Codegen](#codegen)
119
+ - [Ecosystem](#ecosystem)
120
+ - [Benchmark](#benchmark)
121
+ - [Compile](#benchmark-compile)
122
+ - [Validate](#benchmark-validate)
123
+ - [Compression](#benchmark-compression)
124
+ - [Contribute](#contribute)
125
+
126
+ <a name="usage"></a>
127
+
128
+ ## Usage
129
+
130
+ The following shows general usage.
131
+
132
+ ```typescript
133
+ import { Type, type Static } from '@sinclair/typebox'
134
+
135
+ //--------------------------------------------------------------------------------------------
136
+ //
137
+ // Let's say you have the following type ...
138
+ //
139
+ //--------------------------------------------------------------------------------------------
140
+
141
+ type T = {
142
+ id: string,
143
+ name: string,
144
+ timestamp: number
145
+ }
146
+
147
+ //--------------------------------------------------------------------------------------------
148
+ //
149
+ // ... you can express this type in the following way.
150
+ //
151
+ //--------------------------------------------------------------------------------------------
152
+
153
+ const T = Type.Object({ // const T = {
154
+ id: Type.String(), // type: 'object',
155
+ name: Type.String(), // properties: {
156
+ timestamp: Type.Integer() // id: {
157
+ }) // type: 'string'
158
+ // },
159
+ // name: {
160
+ // type: 'string'
161
+ // },
162
+ // timestamp: {
163
+ // type: 'integer'
164
+ // }
165
+ // },
166
+ // required: [
167
+ // 'id',
168
+ // 'name',
169
+ // 'timestamp'
170
+ // ]
171
+ // }
172
+
173
+ //--------------------------------------------------------------------------------------------
174
+ //
175
+ // ... then infer back to the original static type this way.
176
+ //
177
+ //--------------------------------------------------------------------------------------------
178
+
179
+ type T = Static<typeof T> // type T = {
180
+ // id: string,
181
+ // name: string,
182
+ // timestamp: number
183
+ // }
184
+
185
+ //--------------------------------------------------------------------------------------------
186
+ //
187
+ // ... or use the type to parse JavaScript values.
188
+ //
189
+ //--------------------------------------------------------------------------------------------
190
+
191
+ import { Value } from '@sinclair/typebox/value'
192
+
193
+ const R = Value.Parse(T, value) // const R: {
194
+ // id: string,
195
+ // name: string,
196
+ // timestamp: number
197
+ // }
198
+ ```
199
+
200
+ <a name='types'></a>
201
+
202
+ ## Types
203
+
204
+ TypeBox types are Json Schema fragments that compose into more complex types. Each fragment is structured such that any Json Schema compliant validator can runtime assert a value the same way TypeScript will statically assert a type. TypeBox offers a set of Json Types which are used to create Json Schema compliant schematics as well as a JavaScript type set used to create schematics for constructs native to JavaScript.
205
+
206
+ <a name='types-json'></a>
207
+
208
+ ### Json Types
209
+
210
+ The following table lists the supported Json types. These types are fully compatible with the Json Schema Draft 7 specification.
211
+
212
+ ```typescript
213
+ ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
214
+ │ TypeBox │ TypeScript │ Json Schema │
215
+
216
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
217
+ │ const T = Type.Any() │ type T = any │ const T = { } │
218
+
219
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
220
+ │ const T = Type.Unknown() │ type T = unknown │ const T = { } │
221
+
222
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
223
+ const T = Type.String() type T = string const T = {
224
+ │ │ │ type: 'string'
225
+ │ │ │ } │
226
+
227
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
228
+ const T = Type.Number() type T = number const T = {
229
+ │ │ │ type: 'number'
230
+ │ │ │ } │
231
+
232
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
233
+ const T = Type.Integer() type T = number const T = {
234
+ │ │ │ type: 'integer'
235
+ │ │ │ } │
236
+
237
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
238
+ const T = Type.Boolean() type T = boolean const T = {
239
+ │ │ │ type: 'boolean'
240
+ │ │ │ } │
241
+
242
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
243
+ const T = Type.Null() type T = null const T = {
244
+ │ │ │ type: 'null'
245
+ │ │ │ } │
246
+
247
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
248
+ const T = Type.Literal(42) type T = 42 const T = { │
249
+ │ │ │ const: 42,
250
+ │ │ │ type: 'number'
251
+ │ │ │ } │
252
+
253
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
254
+ const T = Type.Array( type T = number[] const T = {
255
+ Type.Number() │ │ type: 'array',
256
+ ) │ │ items: {
257
+ │ │ │ type: 'number'
258
+ │ │ │ }
259
+ │ │ │ } │
260
+
261
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
262
+ const T = Type.Object({ type T = { const T = {
263
+ x: Type.Number(), x: number, type: 'object',
264
+ y: Type.Number() y: number required: ['x', 'y'],
265
+ }) } │ properties: {
266
+ │ │ │ x: {
267
+ │ │ │ type: 'number'
268
+ │ │ │ },
269
+ │ │ │ y: {
270
+ │ │ │ type: 'number'
271
+ │ │ │ }
272
+ │ │ │ }
273
+ │ │ │ } │
274
+
275
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
276
+ const T = Type.Tuple([ type T = [number, number] const T = { │
277
+ Type.Number(), │ │ type: 'array',
278
+ Type.Number() │ │ items: [{
279
+ ]) │ │ type: 'number' │
280
+ │ │ │ }, {
281
+ │ │ │ type: 'number'
282
+ │ │ │ }],
283
+ │ │ │ additionalItems: false,
284
+ │ │ │ minItems: 2,
285
+ │ │ │ maxItems: 2
286
+ │ │ │ }
287
+ │ │ │ │
288
+
289
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
290
+ enum Foo { enum Foo { const T = {
291
+ A, A, │ anyOf: [{
292
+ B B type: 'number', │
293
+ } } const: 0
294
+ │ │ │ }, {
295
+ const T = Type.Enum(Foo) type T = Foo type: 'number',
296
+ │ │ │ const: 1
297
+ │ │ │ }]
298
+ │ │ │ } │
299
+
300
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
301
+ const T = Type.Const({ type T = { const T = {
302
+ x: 1, │ readonly x: 1, type: 'object',
303
+ y: 2, readonly y: 2 required: ['x', 'y'],
304
+ } as const) } properties: {
305
+ │ │ │ x: {
306
+ │ │ │ type: 'number',
307
+ │ │ │ const: 1
308
+ │ │ │ },
309
+ │ │ │ y: {
310
+ │ │ │ type: 'number',
311
+ │ │ │ const: 2
312
+ │ │ │ }
313
+ │ │ │ }
314
+ │ │ │ } │
315
+
316
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
317
+ const T = Type.KeyOf( │ type T = keyof { const T = { │
318
+ Type.Object({ x: number, anyOf: [{
319
+ x: Type.Number(), y: number type: 'string', │
320
+ y: Type.Number() } const: 'x'
321
+ }) │ │ }, {
322
+ ) │ │ type: 'string',
323
+ │ │ │ const: 'y'
324
+ │ │ │ }]
325
+ │ │ │ } │
326
+
327
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
328
+ const T = Type.Union([ type T = string | number const T = { │
329
+ Type.String(), │ │ anyOf: [{
330
+ Type.Number() │ │ type: 'string' │
331
+ ]) │ │ }, {
332
+ │ │ │ type: 'number'
333
+ │ │ │ }]
334
+ │ │ │ } │
335
+
336
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
337
+ const T = Type.Intersect([ type T = { const T = {
338
+ Type.Object({ x: number │ allOf: [{
339
+ x: Type.Number() │ } & { type: 'object',
340
+ }), │ y: number required: ['x'],
341
+ Type.Object({ │ } │ properties: {
342
+ y: Type.Number() │ │ x: {
343
+ }) │ │ type: 'number'
344
+ ]) │ │ }
345
+ │ │ │ } │
346
+ │ │ │ }, {
347
+ │ │ │ type: 'object', |
348
+ │ │ │ required: ['y'],
349
+ │ │ │ properties: {
350
+ │ │ │ y: {
351
+ │ │ │ type: 'number'
352
+ │ │ │ }
353
+ │ │ │ }
354
+ │ │ │ }]
355
+ │ │ │ } │
356
+
357
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
358
+ const T = Type.Composite([ type T = { const T = {
359
+ Type.Object({ x: number, type: 'object',
360
+ x: Type.Number() y: number required: ['x', 'y'],
361
+ }), } properties: {
362
+ Type.Object({ │ │ x: {
363
+ y: Type.Number() │ │ type: 'number'
364
+ }) │ │ },
365
+ ]) │ │ y: {
366
+ │ │ │ type: 'number'
367
+ │ │ │ }
368
+ │ │ │ }
369
+ │ │ │ } │
370
+
371
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
372
+ const T = Type.Never() type T = never const T = {
373
+ │ │ │ not: {}
374
+ │ │ │ } │
375
+
376
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
377
+ const T = Type.Not( | type T = unknown const T = { │
378
+ Type.String() │ │ not: {
379
+ ) │ │ type: 'string'
380
+ │ │ │ } │
381
+ }
382
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
383
+ const T = Type.Extends( │ type T = const T = { │
384
+ │ Type.String(), string extends number │ const: false,
385
+ │ Type.Number(), ? true type: 'boolean'
386
+ Type.Literal(true), : false }
387
+ Type.Literal(false) │ │ │
388
+ │ ) │ │ │
389
+
390
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
391
+ const T = Type.Extract( type T = Extract< const T = {
392
+ Type.Union([ │ string | number, type: 'string'
393
+ Type.String(), string }
394
+ Type.Number(), > │ │
395
+ ]), │ │ │
396
+ Type.String() │ │ │
397
+ │ ) │ │ │
398
+
399
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
400
+ const T = Type.Exclude( type T = Exclude< const T = {
401
+ Type.Union([ │ string | number, type: 'number'
402
+ Type.String(), string }
403
+ Type.Number(), > │ │
404
+ ]), │ │ │
405
+ Type.String() │ │ │
406
+ │ ) │ │ │
407
+
408
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
409
+ const T = Type.Mapped( │ type T = { const T = {
410
+ Type.Union([ │ [_ in 'x' | 'y'] : number type: 'object',
411
+ Type.Literal('x'), } required: ['x', 'y'],
412
+ Type.Literal('y') │ │ properties: {
413
+ ]), │ │ x: {
414
+ () => Type.Number() │ │ type: 'number'
415
+ ) │ │ },
416
+ │ │ │ y: {
417
+ │ │ │ type: 'number'
418
+ │ │ │ }
419
+ │ │ │ }
420
+ │ │ │ } │
421
+
422
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
423
+ const U = Type.Union([ │ type U = 'open' | 'close' const T = { │
424
+ Type.Literal('open'), │ │ type: 'string',
425
+ Type.Literal('close') type T = `on${U}` pattern: '^on(open|close)$'
426
+ ]) │ │ }
427
+ │ │ │
428
+ const T = Type │ │ │
429
+ .TemplateLiteral([ │ │ │
430
+ Type.Literal('on'), │ │ │
431
+ U │ │ │
432
+ │ ]) │ │ │
433
+
434
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
435
+ const T = Type.Record( type T = Record< const T = {
436
+ Type.String(), string, │ type: 'object',
437
+ Type.Number() number patternProperties: {
438
+ ) > '^.*$': {
439
+ │ │ │ type: 'number'
440
+ │ │ │ }
441
+ │ │ │ }
442
+ │ │ │ } │
443
+
444
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
445
+ const T = Type.Partial( type T = Partial<{ const T = {
446
+ Type.Object({ x: number, type: 'object', │
447
+ x: Type.Number(), y: number properties: { │
448
+ y: Type.Number() | }> x: {
449
+ }) │ │ type: 'number'
450
+ ) │ │ },
451
+ │ │ │ y: {
452
+ │ │ │ type: 'number'
453
+ │ │ │ }
454
+ │ │ │ }
455
+ │ │ │ } │
456
+
457
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
458
+ const T = Type.Required( type T = Required<{ const T = {
459
+ Type.Object({ │ x?: number, type: 'object',
460
+ x: Type.Optional( y?: number required: ['x', 'y'],
461
+ Type.Number() | }> properties: {
462
+ ), │ │ x: {
463
+ y: Type.Optional( │ │ type: 'number'
464
+ Type.Number() │ │ },
465
+ ) │ │ y: {
466
+ }) │ │ type: 'number'
467
+ ) │ │ }
468
+ │ │ │ }
469
+ │ │ │ } │
470
+
471
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
472
+ const T = Type.Pick( type T = Pick<{ const T = { │
473
+ Type.Object({ x: number, type: 'object',
474
+ x: Type.Number(), │ y: number │ required: ['x'],
475
+ y: Type.Number() }, 'x'> properties: { │
476
+ }), ['x'] |x: {
477
+ ) │ │ type: 'number'
478
+ │ │ │ }
479
+ │ │ │ }
480
+ │ │ │ } │
481
+
482
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
483
+ const T = Type.Omit( type T = Omit<{ const T = { │
484
+ Type.Object({ x: number, type: 'object',
485
+ x: Type.Number(), │ y: number │ required: ['y'],
486
+ y: Type.Number() }, 'x'> properties: { │
487
+ }), ['x'] |y: {
488
+ ) │ │ type: 'number'
489
+ │ │ │ }
490
+ │ │ │ }
491
+ │ │ │ } │
492
+
493
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
494
+ const T = Type.Index( │ type T = { const T = {
495
+ Type.Object({ x: number, │ type: 'number'
496
+ x: Type.Number(), │ y: string }
497
+ y: Type.String() }['x'] │ │
498
+ }), ['x'] │ │ │
499
+ │ ) │ │ │
500
+
501
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
502
+ const A = Type.Tuple([ │ type A = [0, 1] const T = {
503
+ Type.Literal(0), type B = [2, 3] type: 'array', │
504
+ Type.Literal(1) │ type T = [ items: [
505
+ │ ]) ...A, │ { const: 0 }, │
506
+ │ const B = Type.Tuple([ ...B │ { const: 1 },
507
+ | Type.Literal(2), │ ] { const: 2 },
508
+ | Type.Literal(3) │ │ { const: 3 }
509
+ │ ]) │ │ ],
510
+ │ const T = Type.Tuple([ │ │ additionalItems: false,
511
+ | ...Type.Rest(A), │ │ minItems: 4,
512
+ | ...Type.Rest(B) │ │ maxItems: 4
513
+ │ ]) │ │ } │
514
+
515
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
516
+ const T = Type.Uncapitalize( type T = Uncapitalize< const T = {
517
+ Type.Literal('Hello') 'Hello' type: 'string',
518
+ ) > const: 'hello'
519
+ │ │ │ } │
520
+
521
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
522
+ const T = Type.Capitalize( type T = Capitalize< const T = {
523
+ Type.Literal('hello') 'hello' type: 'string',
524
+ ) > const: 'Hello'
525
+ │ │ │ } │
526
+
527
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
528
+ const T = Type.Uppercase( type T = Uppercase< const T = {
529
+ Type.Literal('hello') 'hello' type: 'string',
530
+ ) > const: 'HELLO'
531
+ │ │ │ } │
532
+
533
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
534
+ const T = Type.Lowercase( type T = Lowercase< const T = {
535
+ Type.Literal('HELLO') 'HELLO' type: 'string',
536
+ ) > const: 'hello'
537
+ │ │ │ } │
538
+
539
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
540
+ │ const R = Type.Ref('T') │ type R = unknown │ const R = { $ref: 'T' } │
541
+ │ │ │ │
542
+ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
543
+ ```
544
+
545
+ <a name='types-javascript'></a>
546
+
547
+ ### JavaScript Types
548
+
549
+ TypeBox provides an extended type set that can be used to create schematics for common JavaScript constructs. These types can not be used with any standard Json Schema validator; but can be used to frame schematics for interfaces that may receive Json validated data. JavaScript types are prefixed with the `[JavaScript]` JSDoc comment for convenience. The following table lists the supported types.
550
+
551
+ ```typescript
552
+ ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
553
+ │ TypeBox │ TypeScript │ Extended Schema │
554
+
555
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
556
+ const T = Type.Constructor([ type T = new ( const T = {
557
+ Type.String(), arg0: string, type: 'Constructor',
558
+ Type.Number() arg0: number parameters: [{
559
+ ], Type.Boolean()) ) => boolean │ type: 'string' │
560
+ │ │ │ }, {
561
+ │ │ │ type: 'number'
562
+ │ │ │ }],
563
+ │ │ │ returns: {
564
+ │ │ │ type: 'boolean'
565
+ │ │ │ }
566
+ │ │ │ } │
567
+
568
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
569
+ const T = Type.Function([ type T = ( const T = {
570
+ | Type.String(), arg0: string, type: 'Function',
571
+ Type.Number() arg1: number parameters: [{
572
+ ], Type.Boolean()) ) => boolean │ type: 'string' │
573
+ │ │ │ }, {
574
+ │ │ │ type: 'number'
575
+ │ │ │ }],
576
+ │ │ │ returns: {
577
+ │ │ │ type: 'boolean'
578
+ │ │ │ }
579
+ │ │ │ } │
580
+
581
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
582
+ const T = Type.Promise( type T = Promise<string> const T = {
583
+ Type.String() │ │ type: 'Promise',
584
+ ) │ │ item: {
585
+ │ │ │ type: 'string'
586
+ │ │ │ }
587
+ │ │ │ } │
588
+
589
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
590
+ const T = type T = const T = {
591
+ Type.AsyncIterator( AsyncIterableIterator< type: 'AsyncIterator',
592
+ Type.String() string items: {
593
+ ) > type: 'string'
594
+ │ │ │ }
595
+ │ │ │ } │
596
+
597
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
598
+ const T = Type.Iterator( type T = const T = {
599
+ Type.String() IterableIterator<string> type: 'Iterator',
600
+ ) │ │ items: {
601
+ │ │ │ type: 'string'
602
+ │ │ │ }
603
+ │ │ │ } │
604
+
605
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
606
+ const T = Type.RegExp(/abc/i) type T = string const T = {
607
+ │ │ │ type: 'RegExp'
608
+ │ │ │ source: 'abc'
609
+ │ │ │ flags: 'i'
610
+ │ │ │ } │
611
+
612
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
613
+ const T = Type.Uint8Array() type T = Uint8Array const T = {
614
+ │ │ │ type: 'Uint8Array'
615
+ │ │ │ } │
616
+
617
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
618
+ const T = Type.Date() type T = Date const T = {
619
+ │ │ │ type: 'Date'
620
+ │ │ │ } │
621
+
622
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
623
+ const T = Type.Undefined() type T = undefined const T = {
624
+ │ │ │ type: 'undefined'
625
+ │ │ │ } │
626
+
627
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
628
+ const T = Type.Symbol() type T = symbol const T = {
629
+ │ │ │ type: 'symbol'
630
+ │ │ │ } │
631
+
632
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
633
+ const T = Type.BigInt() type T = bigint const T = {
634
+ │ │ │ type: 'bigint'
635
+ │ │ │ } │
636
+
637
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
638
+ const T = Type.Void() type T = void const T = {
639
+ │ │ │ type: 'void'
640
+ │ │ │ } │
641
+ │ │ │ │
642
+ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
643
+ ```
644
+
645
+ <a name='types-options'></a>
646
+
647
+ ### Options
648
+
649
+ You can pass Json Schema options on the last argument of any given type. Option hints specific to each type are provided for convenience.
650
+
651
+ ```typescript
652
+ // String must be an email
653
+ const T = Type.String({ // const T = {
654
+ format: 'email' // type: 'string',
655
+ }) // format: 'email'
656
+ // }
657
+
658
+ // Number must be a multiple of 2
659
+ const T = Type.Number({ // const T = {
660
+ multipleOf: 2 // type: 'number',
661
+ }) // multipleOf: 2
662
+ // }
663
+
664
+ // Array must have at least 5 integer values
665
+ const T = Type.Array(Type.Integer(), { // const T = {
666
+ minItems: 5 // type: 'array',
667
+ }) // minItems: 5,
668
+ // items: {
669
+ // type: 'integer'
670
+ // }
671
+ // }
672
+ ```
673
+
674
+ <a name='types-properties'></a>
675
+
676
+ ### Properties
677
+
678
+ Object properties can be modified with Readonly and Optional. The following table shows how these modifiers map between TypeScript and Json Schema.
679
+
680
+ ```typescript
681
+ ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
682
+ │ TypeBox │ TypeScript │ Json Schema │
683
+
684
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
685
+ const T = Type.Object({ type T = { const T = {
686
+ name: Type.ReadonlyOptional( readonly name?: string type: 'object',
687
+ Type.String() │ } properties: {
688
+ ) │ │ name: {
689
+ }) │ │ type: 'string'
690
+ │ │ │ }
691
+ │ │ │ }
692
+ │ │ │ } │
693
+
694
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
695
+ const T = Type.Object({ type T = { const T = {
696
+ name: Type.Readonly( readonly name: string type: 'object', │
697
+ Type.String() │ } properties: {
698
+ ) │ │ name: {
699
+ }) │ │ type: 'string'
700
+ │ │ │ }
701
+ │ │ │ },
702
+ │ │ │ required: ['name']
703
+ │ │ │ } │
704
+
705
+ ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
706
+ const T = Type.Object({ type T = { const T = {
707
+ name: Type.Optional( name?: string type: 'object',
708
+ Type.String() │ } properties: {
709
+ ) │ │ name: {
710
+ }) │ │ type: 'string'
711
+ │ │ │ }
712
+ │ │ │ }
713
+ │ │ │ } │
714
+ │ │ │ │
715
+ └────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
716
+ ```
717
+
718
+ <a name='types-generics'></a>
719
+
720
+ ### Generic Types
721
+
722
+ Generic types can be created with generic functions.
723
+
724
+ ```typescript
725
+ const Nullable = <T extends TSchema>(T: T) => { // type Nullable<T> = T | null
726
+ return Type.Union([T, Type.Null()])
727
+ }
728
+
729
+ const T = Nullable(Type.String()) // type T = Nullable<string>
730
+ ```
731
+
732
+ <a name='types-recursive'></a>
733
+
734
+ ### Recursive Types
735
+
736
+ Use the Recursive function to create recursive types.
737
+
738
+ ```typescript
739
+ const Node = Type.Recursive(This => Type.Object({ // const Node = {
740
+ id: Type.String(), // $id: 'Node',
741
+ nodes: Type.Array(This) // type: 'object',
742
+ }), { $id: 'Node' }) // properties: {
743
+ // id: {
744
+ // type: 'string'
745
+ // },
746
+ // nodes: {
747
+ // type: 'array',
748
+ // items: {
749
+ // $ref: 'Node'
750
+ // }
751
+ // }
752
+ // },
753
+ // required: [
754
+ // 'id',
755
+ // 'nodes'
756
+ // ]
757
+ // }
758
+
759
+ type Node = Static<typeof Node> // type Node = {
760
+ // id: string
761
+ // nodes: Node[]
762
+ // }
763
+
764
+ function test(node: Node) {
765
+ const id = node.nodes[0].nodes[0].id // id is string
766
+ }
767
+ ```
768
+
769
+ <a name='types-modules'></a>
770
+
771
+ ### Module Types
772
+
773
+ Module types are containers for a set of referential types. Modules act as namespaces, enabling types to reference one another via string identifiers. Modules support both singular and mutually recursive references, as well as deferred dereferencing for computed types such as Partial. Types imported from a module are expressed using the Json Schema `$defs` keyword.
774
+
775
+ ```typescript
776
+ const Module = Type.Module({
777
+ PartialUser: Type.Partial(Type.Ref('User')), // TComputed<'Partial', [TRef<'User'>]>
778
+
779
+ User: Type.Object({ // TObject<{
780
+ id: Type.String(), // user: TString,
781
+ name: Type.String(), // name: TString,
782
+ email: Type.String() // email: TString
783
+ }), // }>
784
+ })
785
+ const User = Module.Import('User') // const User: TImport<{...}, 'User'>
786
+
787
+ type User = Static<typeof User> // type User = {
788
+ // id: string,
789
+ // name: string,
790
+ // email: string
791
+ // }
792
+
793
+ const PartialUser = Module.Import('PartialUser') // const PartialUser: TImport<{...}, 'PartialUser'>
794
+
795
+ type PartialUser = Static<typeof PartialUser> // type PartialUser = {
796
+ // id?: string,
797
+ // name?: string,
798
+ // email?: string
799
+ // }
800
+ ```
801
+
802
+ <a name='types-template-literal'></a>
803
+
804
+ ### Template Literal Types
805
+
806
+ TypeBox supports template literal types with the TemplateLiteral function. This type can be created using a syntax similar to the TypeScript template literal syntax or composed from exterior types. TypeBox encodes template literals as regular expressions which enables the template to be checked by Json Schema validators. This type also supports regular expression parsing that enables template patterns to be used for generative types. The following shows both TypeScript and TypeBox usage.
807
+
808
+ ```typescript
809
+ // TypeScript
810
+
811
+ type K = `prop${'A'|'B'|'C'}` // type T = 'propA' | 'propB' | 'propC'
812
+
813
+ type R = Record<K, string> // type R = {
814
+ // propA: string
815
+ // propB: string
816
+ // propC: string
817
+ // }
818
+
819
+ // TypeBox
820
+
821
+ const K = Type.TemplateLiteral('prop${A|B|C}') // const K: TTemplateLiteral<[
822
+ // TLiteral<'prop'>,
823
+ // TUnion<[
824
+ // TLiteral<'A'>,
825
+ // TLiteral<'B'>,
826
+ // TLiteral<'C'>,
827
+ // ]>
828
+ // ]>
829
+
830
+ const R = Type.Record(K, Type.String()) // const R: TObject<{
831
+ // propA: TString,
832
+ // propB: TString,
833
+ // propC: TString,
834
+ // }>
835
+ ```
836
+
837
+ <a name='types-indexed'></a>
838
+
839
+ ### Indexed Access Types
840
+
841
+ TypeBox supports indexed access types with the Index function. This function enables uniform access to interior property and element types without having to extract them from the underlying schema representation. Index types are supported for Object, Array, Tuple, Union and Intersect types.
842
+
843
+ ```typescript
844
+ const T = Type.Object({ // type T = {
845
+ x: Type.Number(), // x: number,
846
+ y: Type.String(), // y: string,
847
+ z: Type.Boolean() // z: boolean
848
+ }) // }
849
+
850
+ const A = Type.Index(T, ['x']) // type A = T['x']
851
+ //
852
+ // ... evaluated as
853
+ //
854
+ // const A: TNumber
855
+
856
+ const B = Type.Index(T, ['x', 'y']) // type B = T['x' | 'y']
857
+ //
858
+ // ... evaluated as
859
+ //
860
+ // const B: TUnion<[
861
+ // TNumber,
862
+ // TString,
863
+ // ]>
864
+
865
+ const C = Type.Index(T, Type.KeyOf(T)) // type C = T[keyof T]
866
+ //
867
+ // ... evaluated as
868
+ //
869
+ // const C: TUnion<[
870
+ // TNumber,
871
+ // TString,
872
+ // TBoolean
873
+ // ]>
874
+ ```
875
+
876
+ <a name='types-mapped'></a>
877
+
878
+ ### Mapped Types
879
+
880
+ TypeBox supports mapped types with the Mapped function. This function accepts two arguments, the first is a union type typically derived from KeyOf, the second is a mapping function that receives a mapping key `K` that can be used to index properties of a type. The following implements a mapped type that remaps each property to be `T | null`.
881
+
882
+ ```typescript
883
+ const T = Type.Object({ // type T = {
884
+ x: Type.Number(), // x: number,
885
+ y: Type.String(), // y: string,
886
+ z: Type.Boolean() // z: boolean
887
+ }) // }
888
+
889
+ const M = Type.Mapped(Type.KeyOf(T), K => { // type M = { [K in keyof T]: T[K] | null }
890
+ return Type.Union([Type.Index(T, K), Type.Null()]) //
891
+ }) // ... evaluated as
892
+ //
893
+ // const M: TObject<{
894
+ // x: TUnion<[TNumber, TNull]>,
895
+ // y: TUnion<[TString, TNull]>,
896
+ // z: TUnion<[TBoolean, TNull]>
897
+ // }>
898
+ ```
899
+
900
+ <a name='types-conditional'></a>
901
+
902
+ ### Conditional Types
903
+
904
+ TypeBox supports runtime conditional types with the Extends function. This function performs a structural assignability check against the first (`left`) and second (`right`) arguments and will return either the third (`true`) or fourth (`false`) argument based on the result. The conditional types Exclude and Extract are also supported. The following shows both TypeScript and TypeBox examples of conditional types.
905
+
906
+ ```typescript
907
+ // Extends
908
+ const A = Type.Extends( // type A = string extends number ? 1 : 2
909
+ Type.String(), //
910
+ Type.Number(), // ... evaluated as
911
+ Type.Literal(1), //
912
+ Type.Literal(2) // const A: TLiteral<2>
913
+ )
914
+
915
+ // Extract
916
+ const B = Type.Extract( // type B = Extract<1 | 2 | 3, 1>
917
+ Type.Union([ //
918
+ Type.Literal(1), // ... evaluated as
919
+ Type.Literal(2), //
920
+ Type.Literal(3) // const B: TLiteral<1>
921
+ ]),
922
+ Type.Literal(1)
923
+ )
924
+
925
+ // Exclude
926
+ const C = Type.Exclude( // type C = Exclude<1 | 2 | 3, 1>
927
+ Type.Union([ //
928
+ Type.Literal(1), // ... evaluated as
929
+ Type.Literal(2), //
930
+ Type.Literal(3) // const C: TUnion<[
931
+ ]), // TLiteral<2>,
932
+ Type.Literal(1) // TLiteral<3>,
933
+ ) // ]>
934
+ ```
935
+
936
+ <a name='types-transform'></a>
937
+
938
+ ### Transform Types
939
+
940
+ TypeBox supports value decoding and encoding with Transform types. These types work in tandem with the Encode and Decode functions available on the Value and TypeCompiler submodules. Transform types can be used to convert Json encoded values into constructs more natural to JavaScript. The following creates a Transform type to decode numbers into Dates using the Value submodule.
941
+
942
+ ```typescript
943
+ import { Value } from '@sinclair/typebox/value'
944
+
945
+ const T = Type.Transform(Type.Number())
946
+ .Decode(value => new Date(value)) // decode: number to Date
947
+ .Encode(value => value.getTime()) // encode: Date to number
948
+
949
+ const D = Value.Decode(T, 0) // const D = Date(1970-01-01T00:00:00.000Z)
950
+ const E = Value.Encode(T, D) // const E = 0
951
+ ```
952
+ Use the StaticEncode or StaticDecode types to infer a Transform type.
953
+ ```typescript
954
+ import { Static, StaticDecode, StaticEncode } from '@sinclair/typebox'
955
+
956
+ const T = Type.Transform(Type.Array(Type.Number(), { uniqueItems: true }))
957
+ .Decode(value => new Set(value))
958
+ .Encode(value => [...value])
959
+
960
+ type D = StaticDecode<typeof T> // type D = Set<number>
961
+ type E = StaticEncode<typeof T> // type E = Array<number>
962
+ type T = Static<typeof T> // type T = Array<number>
963
+ ```
964
+
965
+ <a name='types-unsafe'></a>
966
+
967
+ ### Unsafe Types
968
+
969
+ TypeBox supports user defined types with Unsafe. This type allows you to specify both schema representation and inference type. The following creates an Unsafe type with a number schema that infers as string.
970
+
971
+ ```typescript
972
+ const T = Type.Unsafe<string>({ type: 'number' }) // const T = { type: 'number' }
973
+
974
+ type T = Static<typeof T> // type T = string - ?
975
+ ```
976
+ The Unsafe type is often used to create schematics for extended specifications like OpenAPI.
977
+ ```typescript
978
+
979
+ const Nullable = <T extends TSchema>(schema: T) => Type.Unsafe<Static<T> | null>({
980
+ ...schema, nullable: true
981
+ })
982
+
983
+ const T = Nullable(Type.String()) // const T = {
984
+ // type: 'string',
985
+ // nullable: true
986
+ // }
987
+
988
+ type T = Static<typeof T> // type T = string | null
989
+
990
+ const StringEnum = <T extends string[]>(values: [...T]) => Type.Unsafe<T[number]>({
991
+ type: 'string', enum: values
992
+ })
993
+ const S = StringEnum(['A', 'B', 'C']) // const S = {
994
+ // enum: ['A', 'B', 'C']
995
+ // }
996
+
997
+ type S = Static<typeof T> // type S = 'A' | 'B' | 'C'
998
+ ```
999
+ <a name='types-guard'></a>
1000
+
1001
+ ### TypeGuard
1002
+
1003
+ TypeBox can check its own types with the TypeGuard module. This module is written for type introspection and provides structural tests for every built-in TypeBox type. Functions of this module return `is` guards which can be used with control flow assertions to obtain schema inference for unknown values. The following guards that the value `T` is TString.
1004
+
1005
+ ```typescript
1006
+ import { TypeGuard, Kind } from '@sinclair/typebox'
1007
+
1008
+ const T = { [Kind]: 'String', type: 'string' }
1009
+
1010
+ if(TypeGuard.IsString(T)) {
1011
+
1012
+ // T is TString
1013
+ }
1014
+ ```
1015
+
1016
+ <a name='values'></a>
1017
+
1018
+ ## Values
1019
+
1020
+ TypeBox provides an optional Value submodule that can be used to perform structural operations on JavaScript values. This submodule includes functionality to create, check and cast values from types as well as check equality, clone, diff and patch JavaScript values. This submodule is provided via optional import.
1021
+
1022
+ ```typescript
1023
+ import { Value } from '@sinclair/typebox/value'
1024
+ ```
1025
+
1026
+ <a name='values-assert'></a>
1027
+
1028
+ ### Assert
1029
+
1030
+ Use the Assert function to assert a value is valid.
1031
+
1032
+ ```typescript
1033
+ let value: unknown = 1
1034
+
1035
+ Value.Assert(Type.Number(), value) // throws AssertError if invalid
1036
+ ```
1037
+
1038
+ <a name='values-create'></a>
1039
+
1040
+ ### Create
1041
+
1042
+ Use the Create function to create a value from a type. TypeBox will use default values if specified.
1043
+
1044
+ ```typescript
1045
+ const T = Type.Object({ x: Type.Number(), y: Type.Number({ default: 42 }) })
1046
+
1047
+ const A = Value.Create(T) // const A = { x: 0, y: 42 }
1048
+ ```
1049
+
1050
+ <a name='values-clone'></a>
1051
+
1052
+ ### Clone
1053
+
1054
+ Use the Clone function to deeply clone a value.
1055
+
1056
+ ```typescript
1057
+ const A = Value.Clone({ x: 1, y: 2, z: 3 }) // const A = { x: 1, y: 2, z: 3 }
1058
+ ```
1059
+
1060
+ <a name='values-check'></a>
1061
+
1062
+ ### Check
1063
+
1064
+ Use the Check function to type check a value.
1065
+
1066
+ ```typescript
1067
+ const T = Type.Object({ x: Type.Number() })
1068
+
1069
+ const R = Value.Check(T, { x: 1 }) // const R = true
1070
+ ```
1071
+
1072
+ <a name='values-convert'></a>
1073
+
1074
+ ### Convert
1075
+
1076
+ Use the Convert function to convert a value into its target type if a reasonable conversion is possible. This function may return an invalid value and should be checked before use. Its return type is `unknown`.
1077
+
1078
+ ```typescript
1079
+ const T = Type.Object({ x: Type.Number() })
1080
+
1081
+ const R1 = Value.Convert(T, { x: '3.14' }) // const R1 = { x: 3.14 }
1082
+
1083
+ const R2 = Value.Convert(T, { x: 'not a number' }) // const R2 = { x: 'not a number' }
1084
+ ```
1085
+
1086
+ <a name='values-clean'></a>
1087
+
1088
+ ### Clean
1089
+
1090
+ Use Clean to remove excess properties from a value. This function does not check the value and returns an unknown type. You should Check the result before use. Clean is a mutable operation. To avoid mutation, Clone the value first.
1091
+
1092
+ ```typescript
1093
+ const T = Type.Object({
1094
+ x: Type.Number(),
1095
+ y: Type.Number()
1096
+ })
1097
+
1098
+ const X = Value.Clean(T, null) // const 'X = null
1099
+
1100
+ const Y = Value.Clean(T, { x: 1 }) // const 'Y = { x: 1 }
1101
+
1102
+ const Z = Value.Clean(T, { x: 1, y: 2, z: 3 }) // const 'Z = { x: 1, y: 2 }
1103
+ ```
1104
+
1105
+ <a name='values-default'></a>
1106
+
1107
+ ### Default
1108
+
1109
+ Use Default to generate missing properties on a value using default schema annotations if available. This function does not check the value and returns an unknown type. You should Check the result before use. Default is a mutable operation. To avoid mutation, Clone the value first.
1110
+
1111
+ ```typescript
1112
+ const T = Type.Object({
1113
+ x: Type.Number({ default: 0 }),
1114
+ y: Type.Number({ default: 0 })
1115
+ })
1116
+
1117
+ const X = Value.Default(T, null) // const 'X = null - non-enumerable
1118
+
1119
+ const Y = Value.Default(T, { }) // const 'Y = { x: 0, y: 0 }
1120
+
1121
+ const Z = Value.Default(T, { x: 1 }) // const 'Z = { x: 1, y: 0 }
1122
+ ```
1123
+
1124
+ <a name='values-cast'></a>
1125
+
1126
+ ### Cast
1127
+
1128
+ Use the Cast function to upcast a value into a target type. This function will retain as much information as possible from the original value. The Cast function is intended to be used in data migration scenarios where existing values need to be upgraded to match a modified type.
1129
+
1130
+ ```typescript
1131
+ const T = Type.Object({ x: Type.Number(), y: Type.Number() }, { additionalProperties: false })
1132
+
1133
+ const X = Value.Cast(T, null) // const X = { x: 0, y: 0 }
1134
+
1135
+ const Y = Value.Cast(T, { x: 1 }) // const Y = { x: 1, y: 0 }
1136
+
1137
+ const Z = Value.Cast(T, { x: 1, y: 2, z: 3 }) // const Z = { x: 1, y: 2 }
1138
+ ```
1139
+
1140
+ <a name='values-decode'></a>
1141
+
1142
+ ### Decode
1143
+
1144
+ Use the Decode function to decode a value from a type or throw if the value is invalid. The return value will infer as the decoded type. This function will run Transform codecs if available.
1145
+
1146
+ ```typescript
1147
+ const A = Value.Decode(Type.String(), 'hello') // const A = 'hello'
1148
+
1149
+ const B = Value.Decode(Type.String(), 42) // throw
1150
+ ```
1151
+ <a name='values-decode'></a>
1152
+
1153
+ ### Encode
1154
+
1155
+ Use the Encode function to encode a value to a type or throw if the value is invalid. The return value will infer as the encoded type. This function will run Transform codecs if available.
1156
+
1157
+ ```typescript
1158
+ const A = Value.Encode(Type.String(), 'hello') // const A = 'hello'
1159
+
1160
+ const B = Value.Encode(Type.String(), 42) // throw
1161
+ ```
1162
+
1163
+ <a name='values-parse'></a>
1164
+
1165
+ ### Parse
1166
+
1167
+ Use the Parse function to parse a value. This function calls the `Clone` `Clean`, `Default`, `Convert`, `Assert` and `Decode` Value functions in this exact order to process a value.
1168
+
1169
+ ```typescript
1170
+ const R = Value.Parse(Type.String(), 'hello') // const R: string = "hello"
1171
+
1172
+ const E = Value.Parse(Type.String(), undefined) // throws AssertError
1173
+ ```
1174
+
1175
+ You can override the order in which functions are run, or omit functions entirely using the following.
1176
+
1177
+ ```typescript
1178
+ // Runs no functions.
1179
+
1180
+ const R = Value.Parse([], Type.String(), 12345)
1181
+
1182
+ // Runs the Assert() function.
1183
+
1184
+ const E = Value.Parse(['Assert'], Type.String(), 12345)
1185
+
1186
+ // Runs the Convert() function followed by the Assert() function.
1187
+
1188
+ const S = Value.Parse(['Convert', 'Assert'], Type.String(), 12345)
1189
+ ```
1190
+
1191
+ <a name='values-equal'></a>
1192
+
1193
+ ### Equal
1194
+
1195
+ Use the Equal function to deeply check for value equality.
1196
+
1197
+ ```typescript
1198
+ const R = Value.Equal( // const R = true
1199
+ { x: 1, y: 2, z: 3 },
1200
+ { x: 1, y: 2, z: 3 }
1201
+ )
1202
+ ```
1203
+
1204
+ <a name='values-hash'></a>
1205
+
1206
+ ### Hash
1207
+
1208
+ Use the Hash function to create a [FNV1A-64](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function) non-cryptographic hash of a value.
1209
+
1210
+ ```typescript
1211
+ const A = Value.Hash({ x: 1, y: 2, z: 3 }) // const A = 2910466848807138541n
1212
+
1213
+ const B = Value.Hash({ x: 1, y: 4, z: 3 }) // const B = 1418369778807423581n
1214
+ ```
1215
+
1216
+ <a name='values-diff'></a>
1217
+
1218
+ ### Diff
1219
+
1220
+ Use the Diff function to generate a sequence of edits that will transform one value into another.
1221
+
1222
+ ```typescript
1223
+ const E = Value.Diff( // const E = [
1224
+ { x: 1, y: 2, z: 3 }, // { type: 'update', path: '/y', value: 4 },
1225
+ { y: 4, z: 5, w: 6 } // { type: 'update', path: '/z', value: 5 },
1226
+ ) // { type: 'insert', path: '/w', value: 6 },
1227
+ // { type: 'delete', path: '/x' }
1228
+ // ]
1229
+ ```
1230
+
1231
+ <a name='values-patch'></a>
1232
+
1233
+ ### Patch
1234
+
1235
+ Use the Patch function to apply a sequence of edits.
1236
+
1237
+ ```typescript
1238
+ const A = { x: 1, y: 2 }
1239
+
1240
+ const B = { x: 3 }
1241
+
1242
+ const E = Value.Diff(A, B) // const E = [
1243
+ // { type: 'update', path: '/x', value: 3 },
1244
+ // { type: 'delete', path: '/y' }
1245
+ // ]
1246
+
1247
+ const C = Value.Patch<typeof B>(A, E) // const C = { x: 3 }
1248
+ ```
1249
+
1250
+ <a name='values-errors'></a>
1251
+
1252
+ ### Errors
1253
+
1254
+ Use the Errors function to enumerate validation errors.
1255
+
1256
+ ```typescript
1257
+ const T = Type.Object({ x: Type.Number(), y: Type.Number() })
1258
+
1259
+ const R = [...Value.Errors(T, { x: '42' })] // const R = [{
1260
+ // schema: { type: 'number' },
1261
+ // path: '/x',
1262
+ // value: '42',
1263
+ // message: 'Expected number'
1264
+ // }, {
1265
+ // schema: { type: 'number' },
1266
+ // path: '/y',
1267
+ // value: undefined,
1268
+ // message: 'Expected number'
1269
+ // }]
1270
+ ```
1271
+
1272
+ <a name='values-mutate'></a>
1273
+
1274
+ ### Mutate
1275
+
1276
+ Use the Mutate function to perform a deep mutable value assignment while retaining internal references.
1277
+
1278
+ ```typescript
1279
+ const Y = { z: 1 } // const Y = { z: 1 }
1280
+ const X = { y: Y } // const X = { y: { z: 1 } }
1281
+ const A = { x: X } // const A = { x: { y: { z: 1 } } }
1282
+
1283
+ Value.Mutate(A, { x: { y: { z: 2 } } }) // A' = { x: { y: { z: 2 } } }
1284
+
1285
+ const R0 = A.x.y.z === 2 // const R0 = true
1286
+ const R1 = A.x.y === Y // const R1 = true
1287
+ const R2 = A.x === X // const R2 = true
1288
+ ```
1289
+
1290
+ <a name='values-pointer'></a>
1291
+
1292
+ ### Pointer
1293
+
1294
+ Use ValuePointer to perform mutable updates on existing values using [RFC6901](https://www.rfc-editor.org/rfc/rfc6901) Json Pointers.
1295
+
1296
+ ```typescript
1297
+ import { ValuePointer } from '@sinclair/typebox/value'
1298
+
1299
+ const A = { x: 0, y: 0, z: 0 }
1300
+
1301
+ ValuePointer.Set(A, '/x', 1) // A' = { x: 1, y: 0, z: 0 }
1302
+ ValuePointer.Set(A, '/y', 1) // A' = { x: 1, y: 1, z: 0 }
1303
+ ValuePointer.Set(A, '/z', 1) // A' = { x: 1, y: 1, z: 1 }
1304
+ ```
1305
+
1306
+
1307
+
1308
+ <a name='syntax'></a>
1309
+
1310
+ ## Syntax Types
1311
+
1312
+ TypeBox provides experimental support for parsing TypeScript annotation syntax into TypeBox types.
1313
+
1314
+ This feature is provided via optional import.
1315
+
1316
+ ```typescript
1317
+ import { Syntax } from '@sinclair/typebox/syntax'
1318
+ ```
1319
+
1320
+ <a name='syntax-create'></a>
1321
+
1322
+ ### Create
1323
+
1324
+ Use the Syntax function to create TypeBox types from TypeScript syntax ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgChQkWIhTYYwBgWKly1OoxZtO3foMkSGEdDXgAVOAF4Uo3AAoABkhwAuOOgCuIPjygAaOFR3Lx8-AkcASjgY2Jj2djhjUwt3cwB5PgArHgYYAB4ECTiS0rLyisrYhNi3OHMAOW9fAOKq9o7OuBqY4PqmsKg2rpHR+MT8AD4JCS5eeut5LEUGfLmeCCJ6ybHKmvWFmyLdk86euDrQlv9h07uy876rv1v7t-GCIA))
1325
+
1326
+ ```typescript
1327
+ const T = Syntax(`{ x: number, y: number }`) // const T: TObject<{
1328
+ // x: TNumber,
1329
+ // y: TNumber
1330
+ // }>
1331
+
1332
+ type T = Static<typeof T> // type T = {
1333
+ // x: number,
1334
+ // y: number
1335
+ // }
1336
+ ```
1337
+
1338
+ <a name="syntax-parameters"></a>
1339
+
1340
+ ### Parameters
1341
+
1342
+ Syntax types can be parameterized to receive exterior types ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgCgJDCOhrwAKnAC8KUbgAUAAyQ4AXHHQBXEHx5QANHFQHjp8wS0BKOK7ev27ODLmKDCgHk+ACseBhgAHgQJd1i4+ITEpLdPN304BQA5EzNLGOSCwqK4VNcbDOz7KHzi2rqPL3wAPikfeRQVNUxNJCV8Ky0ABSxYYCwmCIUm52LUtvhkfyDQ8Kia+o2C0rh0wLAYYFlxycrcpot1zav47fK9g6OJrJzzFuv3m8amoA))
1343
+
1344
+ ```typescript
1345
+ const T = Syntax(`{ x: number, y: number }`) // const T: TObject<{
1346
+ // x: TNumber,
1347
+ // y: TNumber
1348
+ // }>
1349
+
1350
+ const S = Syntax({ T }, `Partial<T>`) // const S: TObject<{
1351
+ // x: TOptional<TNumber>,
1352
+ // y: TOptional<TNumber>
1353
+ // }>
1354
+ ```
1355
+
1356
+
1357
+
1358
+ <a name="syntax-generics"></a>
1359
+
1360
+ ### Generics
1361
+
1362
+ Syntax types support generic parameters in the following way ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgZQJ4DsYEMAecC+cAZlBCHAOQACAzsOgMYA2WwUA9DKmAKYBGEHOxoZsOCgChQkWIhTYYwBgWKly1OoxZtO3foMkSGEdDXgA1HgxjQ4AXhSjcACgAGAHgAaAGjgBNXwAtAD45CTg4HAAuOB84cLhUGID4iIAvGMD4-FcASgkjEzM4ACEsOhpLa2gae0dMFyQqmygCX1cEBOi4Zuh3AEZfAAZh4O8EpJ6rFvcRuEG4IbGEjKnqqFnh337lnPyJLl5S8uBK6Zq65AUld0OeCCJjit6oGlCIiPZ2ODun05fag5Oh8QaCweCIZCoV8Pt0kN0FpM5qshm0ElCMZisSCYRFJvCYnNJgsUWjseSKeDcXBVgTFr4kb5Vv0COjKezsTD8EA))
1363
+
1364
+ ```typescript
1365
+ const Vector = Syntax(`<X, Y, Z> {
1366
+ x: X,
1367
+ y: Y,
1368
+ z: Z
1369
+ }`)
1370
+
1371
+ const BasisVectors = Syntax({ Vector }, `{
1372
+ x: Vector<1, 0, 0>,
1373
+ y: Vector<0, 1, 0>,
1374
+ z: Vector<0, 0, 1>,
1375
+ }`)
1376
+
1377
+ type BasisVectors = Static<typeof BasisVectors> // type BasisVectors = {
1378
+ // x: { x: 1, y: 0, z: 0 },
1379
+ // y: { x: 0, y: 1, z: 0 },
1380
+ // z: { x: 0, y: 0, z: 1 }
1381
+ // }
1382
+ ```
1383
+
1384
+ <a name='syntax-options'></a>
1385
+
1386
+ ### Options
1387
+
1388
+ Options can be passed via the last parameter.
1389
+
1390
+ ```typescript
1391
+ const T = Syntax(`number`, { minimum: 42 }) // const T = {
1392
+ // type: 'number',
1393
+ // minimum: 42
1394
+ // }
1395
+ ```
1396
+
1397
+ <a name='syntax-no-infer'></a>
1398
+
1399
+ ### NoInfer
1400
+
1401
+ Syntax parsing is an expensive type level operation and can impact on language service performance. Use the NoInfer function parse syntax at runtime only.
1402
+
1403
+ ```typescript
1404
+ import { NoInfer } from '@sinclair/typebox/syntax'
1405
+
1406
+ const T = NoInfer(`number | string`) // const T: TSchema = {
1407
+ // anyOf: [
1408
+ // { type: 'number' },
1409
+ // { type: 'string' }
1410
+ // ]
1411
+ // }
1412
+ ```
1413
+
1414
+ <a name='typeregistry'></a>
1415
+
1416
+ ## TypeRegistry
1417
+
1418
+ The TypeBox type system can be extended with additional types and formats using the TypeRegistry and FormatRegistry modules. These modules integrate deeply with TypeBox's internal type checking infrastructure and can be used to create application specific types, or register schematics for alternative specifications.
1419
+
1420
+ <a name='typeregistry-type'></a>
1421
+
1422
+ ### TypeRegistry
1423
+
1424
+ Use the TypeRegistry to register a type. The Kind must match the registered type name.
1425
+
1426
+ ```typescript
1427
+ import { TSchema, Kind, TypeRegistry } from '@sinclair/typebox'
1428
+
1429
+ TypeRegistry.Set('Foo', (schema, value) => value === 'foo')
1430
+
1431
+ const Foo = { [Kind]: 'Foo' } as TSchema
1432
+
1433
+ const A = Value.Check(Foo, 'foo') // const A = true
1434
+
1435
+ const B = Value.Check(Foo, 'bar') // const B = false
1436
+ ```
1437
+
1438
+ <a name='typeregistry-format'></a>
1439
+
1440
+ ### FormatRegistry
1441
+
1442
+ Use the FormatRegistry to register a string format.
1443
+
1444
+ ```typescript
1445
+ import { FormatRegistry } from '@sinclair/typebox'
1446
+
1447
+ FormatRegistry.Set('foo', (value) => value === 'foo')
1448
+
1449
+ const T = Type.String({ format: 'foo' })
1450
+
1451
+ const A = Value.Check(T, 'foo') // const A = true
1452
+
1453
+ const B = Value.Check(T, 'bar') // const B = false
1454
+ ```
1455
+
1456
+ <a name='typecheck'></a>
1457
+
1458
+ ## TypeCheck
1459
+
1460
+ TypeBox types target Json Schema Draft 7 and are compatible with any validator that supports this specification. TypeBox also provides a built-in type checking compiler designed specifically for TypeBox types that offers high performance compilation and value checking.
1461
+
1462
+ The following sections detail using Ajv and the TypeBox compiler infrastructure.
1463
+
1464
+ <a name='typecheck-ajv'></a>
1465
+
1466
+ ## Ajv
1467
+
1468
+ The following shows the recommended setup for Ajv.
1469
+
1470
+ ```bash
1471
+ $ npm install ajv ajv-formats --save
1472
+ ```
1473
+
1474
+ ```typescript
1475
+ import { Type } from '@sinclair/typebox'
1476
+ import addFormats from 'ajv-formats'
1477
+ import Ajv from 'ajv'
1478
+
1479
+ const ajv = addFormats(new Ajv({}), [
1480
+ 'date-time',
1481
+ 'time',
1482
+ 'date',
1483
+ 'email',
1484
+ 'hostname',
1485
+ 'ipv4',
1486
+ 'ipv6',
1487
+ 'uri',
1488
+ 'uri-reference',
1489
+ 'uuid',
1490
+ 'uri-template',
1491
+ 'json-pointer',
1492
+ 'relative-json-pointer',
1493
+ 'regex'
1494
+ ])
1495
+
1496
+ const validate = ajv.compile(Type.Object({
1497
+ x: Type.Number(),
1498
+ y: Type.Number(),
1499
+ z: Type.Number()
1500
+ }))
1501
+
1502
+ const R = validate({ x: 1, y: 2, z: 3 }) // const R = true
1503
+ ```
1504
+
1505
+ <a name='typecheck-typecompiler'></a>
1506
+
1507
+ ### TypeCompiler
1508
+
1509
+ The TypeBox TypeCompiler is a high performance JIT validation compiler that transforms TypeBox types into optimized JavaScript validation routines. The compiler is tuned for fast compilation as well as fast value assertion. It is built to serve as a validation backend that can be integrated into larger applications. It can also be used for code generation.
1510
+
1511
+ The TypeCompiler is provided as an optional import.
1512
+
1513
+ ```typescript
1514
+ import { TypeCompiler } from '@sinclair/typebox/compiler'
1515
+ ```
1516
+
1517
+ Use the Compile function to JIT compile a type. Note that compilation is generally an expensive operation and should only be performed once per type during application start up. TypeBox does not cache previously compiled types, and applications are expected to hold references to each compiled type for the lifetime of the application.
1518
+
1519
+ ```typescript
1520
+ const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck<TObject<{
1521
+ x: Type.Number(), // x: TNumber;
1522
+ y: Type.Number(), // y: TNumber;
1523
+ z: Type.Number() // z: TNumber;
1524
+ })) // }>>
1525
+
1526
+ const R = C.Check({ x: 1, y: 2, z: 3 }) // const R = true
1527
+ ```
1528
+
1529
+ Use the Errors function to generate diagnostic errors for a value. The Errors function will return an iterator that when enumerated; will perform an exhaustive check across the entire value yielding any error found. For performance, this function should only be called after a failed Check. Applications may also choose to yield only the first value to avoid exhaustive error generation.
1530
+
1531
+ ```typescript
1532
+ const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck<TObject<{
1533
+ x: Type.Number(), // x: TNumber;
1534
+ y: Type.Number(), // y: TNumber;
1535
+ z: Type.Number() // z: TNumber;
1536
+ })) // }>>
1537
+
1538
+ const value = { }
1539
+
1540
+ const first = C.Errors(value).First() // const first = {
1541
+ // schema: { type: 'number' },
1542
+ // path: '/x',
1543
+ // value: undefined,
1544
+ // message: 'Expected number'
1545
+ // }
1546
+
1547
+ const all = [...C.Errors(value)] // const all = [{
1548
+ // schema: { type: 'number' },
1549
+ // path: '/x',
1550
+ // value: undefined,
1551
+ // message: 'Expected number'
1552
+ // }, {
1553
+ // schema: { type: 'number' },
1554
+ // path: '/y',
1555
+ // value: undefined,
1556
+ // message: 'Expected number'
1557
+ // }, {
1558
+ // schema: { type: 'number' },
1559
+ // path: '/z',
1560
+ // value: undefined,
1561
+ // message: 'Expected number'
1562
+ // }]
1563
+ ```
1564
+
1565
+ Use the Code function to generate assertion functions as strings. This function can be used to generate code that can be written to disk as importable modules. This technique is sometimes referred to as Ahead of Time (AOT) compilation. The following generates code to check a string.
1566
+
1567
+ ```typescript
1568
+ const C = TypeCompiler.Code(Type.String()) // const C = `return function check(value) {
1569
+ // return (
1570
+ // (typeof value === 'string')
1571
+ // )
1572
+ // }`
1573
+ ```
1574
+
1575
+ <a name='typemap'></a>
1576
+
1577
+ ## TypeMap
1578
+
1579
+ TypeBox offers an external package for bidirectional mapping between TypeBox, Valibot, and Zod type libraries. It also includes syntax parsing support for Valibot and Zod and supports the Standard Schema specification. For more details on TypeMap, refer to the project repository.
1580
+
1581
+ [TypeMap Repository](https://github.com/sinclairzx81/typemap)
1582
+
1583
+ <a name='typemap-usage'></a>
1584
+
1585
+ ### Usage
1586
+
1587
+ TypeMap needs to be installed separately
1588
+
1589
+ ```bash
1590
+ $ npm install @sinclair/typemap
1591
+ ```
1592
+
1593
+ Once installed it offers advanced structural remapping between various runtime type libraries ([Example](https://www.typescriptlang.org/play/?moduleResolution=99&module=199&ts=5.8.0-beta#code/JYWwDg9gTgLgBAbzgFQJ5gKYCEIA8A0cAyqgHYwCGBcAWhACZwC+cAZlBCHAOQACAzsFIBjADYVgUAPQx0GEBTDcAUMuERS-eMjgBeFHJy4AFAAMkuAFxxSAVxAAjDFEKprdx88IAvd-adQzKYAlHBwUlJw6pra1sgA8g4AVhjCMAA8CMphObl5+QWFRcW5ETlWKABy-s4A3NkljU3NBWVhblU1UPUtvX3FbXC+nZ7dDf0TE2VMAHyq0VrEesRklCbIoS1lC-BE1twWfqOuRwE+p87MKmoaiwBKy3T0xkTBAHRgFFD8GMZ2oqJNnltrd4HdrFlJltImEKh4Aj0oU1Bh14XVxkiBjChhcxpjGtMwkA))
1594
+
1595
+ ```typescript
1596
+ import { TypeBox, Syntax, Zod } from '@sinclair/typemap'
1597
+
1598
+ const T = TypeBox(`{ x: number, y: number, z: number }`) // const T: TObject<{
1599
+ // x: TNumber;
1600
+ // y: TNumber;
1601
+ // z: TNumber;
1602
+ // }>
1603
+
1604
+ const S = Syntax(T) // const S: '{ x: number, y: number, z: number }'
1605
+
1606
+ const R = Zod(S).parse(null) // const R: {
1607
+ // x: number;
1608
+ // y: number;
1609
+ // z: number;
1610
+ // }
1611
+ ```
1612
+
1613
+ <a name='typesystem'></a>
1614
+
1615
+ ## TypeSystem
1616
+
1617
+ The TypeBox TypeSystem module provides configurations to use either Json Schema or TypeScript type checking semantics. Configurations made to the TypeSystem module are observed by the TypeCompiler, Value and Error modules.
1618
+
1619
+ <a name='typesystem-policies'></a>
1620
+
1621
+ ### Policies
1622
+
1623
+ TypeBox validates using standard Json Schema assertion policies by default. The TypeSystemPolicy module can override some of these to have TypeBox assert values inline with TypeScript static checks. It also provides overrides for certain checking rules related to non-serializable values (such as void) which can be helpful in Json based protocols such as Json Rpc 2.0.
1624
+
1625
+ The following overrides are available.
1626
+
1627
+ ```typescript
1628
+ import { TypeSystemPolicy } from '@sinclair/typebox/system'
1629
+
1630
+ // Disallow undefined values for optional properties (default is false)
1631
+ //
1632
+ // const A: { x?: number } = { x: undefined } - disallowed when enabled
1633
+
1634
+ TypeSystemPolicy.ExactOptionalPropertyTypes = true
1635
+
1636
+ // Allow arrays to validate as object types (default is false)
1637
+ //
1638
+ // const A: {} = [] - allowed in TS
1639
+
1640
+ TypeSystemPolicy.AllowArrayObject = true
1641
+
1642
+ // Allow numeric values to be NaN or + or - Infinity (default is false)
1643
+ //
1644
+ // const A: number = NaN - allowed in TS
1645
+
1646
+ TypeSystemPolicy.AllowNaN = true
1647
+
1648
+ // Allow void types to check with undefined and null (default is false)
1649
+ //
1650
+ // Used to signal void return on Json-Rpc 2.0 protocol
1651
+
1652
+ TypeSystemPolicy.AllowNullVoid = true
1653
+ ```
1654
+
1655
+ <a name='error-function'></a>
1656
+
1657
+ ## Error Function
1658
+
1659
+ Error messages in TypeBox can be customized by defining an ErrorFunction. This function allows for the localization of error messages as well as enabling custom error messages for custom types. By default, TypeBox will generate messages using the `en-US` locale. To support additional locales, you can replicate the function found in `src/errors/function.ts` and create a locale specific translation. The function can then be set via SetErrorFunction.
1660
+
1661
+ The following example shows an inline error function that intercepts errors for String, Number and Boolean only. The DefaultErrorFunction is used to return a default error message.
1662
+
1663
+
1664
+ ```typescript
1665
+ import { SetErrorFunction, DefaultErrorFunction, ValueErrorType } from '@sinclair/typebox/errors'
1666
+
1667
+ SetErrorFunction((error) => { // i18n override
1668
+ switch(error.errorType) {
1669
+ /* en-US */ case ValueErrorType.String: return 'Expected string'
1670
+ /* fr-FR */ case ValueErrorType.Number: return 'Nombre attendu'
1671
+ /* ko-KR */ case ValueErrorType.Boolean: return '예상 부울'
1672
+ /* en-US */ default: return DefaultErrorFunction(error)
1673
+ }
1674
+ })
1675
+ const T = Type.Object({ // const T: TObject<{
1676
+ x: Type.String(), // TString,
1677
+ y: Type.Number(), // TNumber,
1678
+ z: Type.Boolean() // TBoolean
1679
+ }) // }>
1680
+
1681
+ const E = [...Value.Errors(T, { // const E = [{
1682
+ x: null, // type: 48,
1683
+ y: null, // schema: { ... },
1684
+ z: null // path: '/x',
1685
+ })] // value: null,
1686
+ // message: 'Expected string'
1687
+ // }, {
1688
+ // type: 34,
1689
+ // schema: { ... },
1690
+ // path: '/y',
1691
+ // value: null,
1692
+ // message: 'Nombre attendu'
1693
+ // }, {
1694
+ // type: 14,
1695
+ // schema: { ... },
1696
+ // path: '/z',
1697
+ // value: null,
1698
+ // message: '예상 부울'
1699
+ // }]
1700
+ ```
1701
+
1702
+ <a name='workbench'></a>
1703
+
1704
+ ## TypeBox Workbench
1705
+
1706
+ TypeBox offers a web based code generation tool that can convert TypeScript types into TypeBox types as well as several other ecosystem libraries.
1707
+
1708
+ [TypeBox Workbench Link Here](https://sinclairzx81.github.io/typebox-workbench/)
1709
+
1710
+ <a name='codegen'></a>
1711
+
1712
+ ## TypeBox Codegen
1713
+
1714
+ TypeBox provides a code generation library that can be integrated into toolchains to automate type translation between TypeScript and TypeBox. This library also includes functionality to transform TypeScript types to other ecosystem libraries.
1715
+
1716
+ [TypeBox Codegen Link Here](https://github.com/sinclairzx81/typebox-codegen)
1717
+
1718
+ <a name='ecosystem'></a>
1719
+
1720
+ ## Ecosystem
1721
+
1722
+ The following is a list of community packages that offer general tooling, extended functionality and framework integration support for TypeBox.
1723
+
1724
+ | Package | Description |
1725
+ | ------------- | ------------- |
1726
+ | [drizzle-typebox](https://www.npmjs.com/package/drizzle-typebox) | Generates TypeBox types from Drizzle ORM schemas |
1727
+ | [elysia](https://github.com/elysiajs/elysia) | Fast and friendly Bun web framework |
1728
+ | [fastify-type-provider-typebox](https://github.com/fastify/fastify-type-provider-typebox) | Fastify TypeBox integration with the Fastify Type Provider |
1729
+ | [feathersjs](https://github.com/feathersjs/feathers) | The API and real-time application framework |
1730
+ | [fetch-typebox](https://github.com/erfanium/fetch-typebox) | Drop-in replacement for fetch that brings easy integration with TypeBox |
1731
+ | [@lonli-lokli/fetcher-typebox](https://github.com/Lonli-Lokli/fetcher-ts/tree/master/packages/fetcher-typebox) | A strongly-typed fetch wrapper for TypeScript applications with optional runtime validation using TypeBox |
1732
+ | [h3-typebox](https://github.com/kevinmarrec/h3-typebox) | Schema validation utilities for h3 using TypeBox & Ajv |
1733
+ | [http-wizard](https://github.com/flodlc/http-wizard) | Type safe http client library for Fastify |
1734
+ | [json2typebox](https://github.com/hacxy/json2typebox) | Creating TypeBox code from Json Data |
1735
+ | [nominal-typebox](https://github.com/Coder-Spirit/nominal/tree/main/%40coderspirit/nominal-typebox) | Allows devs to integrate nominal types into TypeBox schemas |
1736
+ | [openapi-box](https://github.com/geut/openapi-box) | Generate TypeBox types from OpenApi IDL + Http client library |
1737
+ | [prismabox](https://github.com/m1212e/prismabox) | Converts a prisma.schema to TypeBox schema matching the database models |
1738
+ | [schema2typebox](https://github.com/xddq/schema2typebox) | Creating TypeBox code from Json Schemas |
1739
+ | [sveltekit-superforms](https://github.com/ciscoheat/sveltekit-superforms) | A comprehensive SvelteKit form library for server and client validation |
1740
+ | [ts2typebox](https://github.com/xddq/ts2typebox) | Creating TypeBox code from Typescript types |
1741
+ | [typebox-cli](https://github.com/gsuess/typebox-cli) | Generate Schema with TypeBox from the CLI |
1742
+ | [typebox-form-parser](https://github.com/jtlapp/typebox-form-parser) | Parses form and query data based on TypeBox schemas |
1743
+ | [typebox-schema-faker](https://github.com/iam-medvedev/typebox-schema-faker) | Generate fake data from TypeBox schemas for testing, prototyping and development |
1744
+
1745
+
1746
+ <a name='benchmark'></a>
1747
+
1748
+ ## Benchmark
1749
+
1750
+ This project maintains a set of benchmarks that measure Ajv, Value and TypeCompiler compilation and validation performance. These benchmarks can be run locally by cloning this repository and running `npm run benchmark`. The results below show for Ajv version 8.12.0 running on Node 20.10.0.
1751
+
1752
+ For additional comparative benchmarks, please refer to [typescript-runtime-type-benchmarks](https://moltar.github.io/typescript-runtime-type-benchmarks/).
1753
+
1754
+ <a name='benchmark-compile'></a>
1755
+
1756
+ ### Compile
1757
+
1758
+ This benchmark measures compilation performance for varying types.
1759
+
1760
+ ```typescript
1761
+ ┌────────────────────────────┬────────────┬──────────────┬──────────────┬──────────────┐
1762
+ (index) Iterations Ajv TypeCompilerPerformance
1763
+ ├────────────────────────────┼────────────┼──────────────┼──────────────┼──────────────┤
1764
+ Literal_String │ 1000 │ ' 211 ms' │ ' 8 ms' │ ' 26.38 x' │
1765
+ Literal_Number │ 1000 │ ' 185 ms' │ ' 5 ms' │ ' 37.00 x' │
1766
+ Literal_Boolean │ 1000 │ ' 195 ms' │ ' 4 ms' │ ' 48.75 x' │
1767
+ Primitive_Number │ 1000 │ ' 149 ms' │ ' 7 ms' │ ' 21.29 x' │
1768
+ Primitive_String │ 1000 │ ' 135 ms' │ ' 5 ms' │ ' 27.00 x' │
1769
+ Primitive_String_Pattern │ 1000 │ ' 193 ms' │ ' 10 ms' │ ' 19.30 x' │
1770
+ Primitive_Boolean │ 1000 │ ' 152 ms' │ ' 4 ms' │ ' 38.00 x' │
1771
+ Primitive_Null │ 1000 │ ' 147 ms' │ ' 4 ms' │ ' 36.75 x' │
1772
+ Object_Unconstrained │ 1000 │ ' 1065 ms' │ ' 26 ms' │ ' 40.96 x' │
1773
+ Object_Constrained │ 1000 │ ' 1183 ms' │ ' 26 ms' │ ' 45.50 x' │
1774
+ Object_Vector3 │ 1000 │ ' 407 ms' │ ' 9 ms' │ ' 45.22 x' │
1775
+ Object_Box3D │ 1000 │ ' 1777 ms' │ ' 24 ms' │ ' 74.04 x' │
1776
+ Tuple_Primitive │ 1000 │ ' 485 ms' │ ' 11 ms' │ ' 44.09 x' │
1777
+ Tuple_Object │ 1000 │ ' 1344 ms' │ ' 17 ms' │ ' 79.06 x' │
1778
+ Composite_Intersect │ 1000 │ ' 606 ms' │ ' 14 ms' │ ' 43.29 x' │
1779
+ Composite_Union │ 1000 │ ' 522 ms' │ ' 17 ms' │ ' 30.71 x' │
1780
+ Math_Vector4 │ 1000 │ ' 851 ms' │ ' 9 ms' │ ' 94.56 x' │
1781
+ Math_Matrix4 │ 1000 │ ' 406 ms' │ ' 10 ms' │ ' 40.60 x' │
1782
+ Array_Primitive_Number │ 1000 │ ' 367 ms' │ ' 6 ms' │ ' 61.17 x' │
1783
+ Array_Primitive_String │ 1000 │ ' 339 ms' │ ' 7 ms' │ ' 48.43 x' │
1784
+ Array_Primitive_Boolean │ 1000 │ ' 325 ms' │ ' 5 ms' │ ' 65.00 x' │
1785
+ Array_Object_Unconstrained │ 1000 │ ' 1863 ms' │ ' 21 ms' │ ' 88.71 x' │
1786
+ Array_Object_Constrained │ 1000 │ ' 1535 ms' │ ' 18 ms' │ ' 85.28 x' │
1787
+ Array_Tuple_Primitive │ 1000 │ ' 829 ms' │ ' 14 ms' │ ' 59.21 x' │
1788
+ Array_Tuple_Object │ 1000 │ ' 1674 ms' │ ' 14 ms' │ ' 119.57 x' │
1789
+ Array_Composite_Intersect │ 1000 │ ' 789 ms' │ ' 13 ms' │ ' 60.69 x' │
1790
+ Array_Composite_Union │ 1000 │ ' 822 ms' │ ' 15 ms' │ ' 54.80 x' │
1791
+ │ Array_Math_Vector4 │ 1000 │ ' 1129 ms' │ ' 14 ms' │ ' 80.64 x' │
1792
+ │ Array_Math_Matrix4 │ 1000 │ ' 673 ms' │ ' 9 ms' │ ' 74.78 x' │
1793
+ └────────────────────────────┴────────────┴──────────────┴──────────────┴──────────────┘
1794
+ ```
1795
+
1796
+ <a name='benchmark-validate'></a>
1797
+
1798
+ ### Validate
1799
+
1800
+ This benchmark measures validation performance for varying types.
1801
+
1802
+ ```typescript
1803
+ ┌────────────────────────────┬────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
1804
+ (index) Iterations ValueCheck Ajv TypeCompilerPerformance
1805
+ ├────────────────────────────┼────────────┼──────────────┼──────────────┼──────────────┼──────────────┤
1806
+ Literal_String │ 1000000 │ ' 17 ms' │ ' 5 ms' │ ' 5 ms' │ ' 1.00 x' │
1807
+ Literal_Number │ 1000000 │ ' 14 ms' │ ' 18 ms' │ ' 9 ms' │ ' 2.00 x' │
1808
+ Literal_Boolean │ 1000000 │ ' 14 ms' │ ' 20 ms' │ ' 9 ms' │ ' 2.22 x' │
1809
+ Primitive_Number │ 1000000 │ ' 17 ms' │ ' 19 ms' │ ' 9 ms' │ ' 2.11 x' │
1810
+ Primitive_String │ 1000000 │ ' 17 ms' │ ' 18 ms' │ ' 10 ms' │ ' 1.80 x' │
1811
+ Primitive_String_Pattern │ 1000000 │ ' 172 ms' │ ' 46 ms' │ ' 41 ms' │ ' 1.12 x' │
1812
+ Primitive_Boolean │ 1000000 │ ' 14 ms' │ ' 19 ms' │ ' 10 ms' │ ' 1.90 x' │
1813
+ Primitive_Null │ 1000000 │ ' 16 ms' │ ' 19 ms' │ ' 9 ms' │ ' 2.11 x' │
1814
+ Object_Unconstrained │ 1000000 │ ' 437 ms' │ ' 28 ms' │ ' 14 ms' │ ' 2.00 x' │
1815
+ Object_Constrained │ 1000000 │ ' 653 ms' │ ' 46 ms' │ ' 37 ms' │ ' 1.24 x' │
1816
+ Object_Vector3 │ 1000000 │ ' 201 ms' │ ' 22 ms' │ ' 12 ms' │ ' 1.83 x' │
1817
+ Object_Box3D │ 1000000 │ ' 961 ms' │ ' 37 ms' │ ' 19 ms' │ ' 1.95 x' │
1818
+ Object_Recursive │ 1000000 │ ' 3715 ms' │ ' 363 ms' │ ' 174 ms' │ ' 2.09 x' │
1819
+ Tuple_Primitive │ 1000000 │ ' 107 ms' │ ' 23 ms' │ ' 11 ms' │ ' 2.09 x' │
1820
+ Tuple_Object │ 1000000 │ ' 375 ms' │ ' 28 ms' │ ' 15 ms' │ ' 1.87 x' │
1821
+ Composite_Intersect │ 1000000 │ ' 377 ms' │ ' 22 ms' │ ' 12 ms' │ ' 1.83 x' │
1822
+ Composite_Union │ 1000000 │ ' 337 ms' │ ' 30 ms' │ ' 17 ms' │ ' 1.76 x' │
1823
+ Math_Vector4 │ 1000000 │ ' 137 ms' │ ' 23 ms' │ ' 11 ms' │ ' 2.09 x' │
1824
+ Math_Matrix4 │ 1000000 │ ' 576 ms' │ ' 37 ms' │ ' 28 ms' │ ' 1.32 x' │
1825
+ Array_Primitive_Number │ 1000000 │ ' 145 ms' │ ' 23 ms' │ ' 12 ms' │ ' 1.92 x' │
1826
+ Array_Primitive_String │ 1000000 │ ' 152 ms' │ ' 22 ms' │ ' 13 ms' │ ' 1.69 x' │
1827
+ Array_Primitive_Boolean │ 1000000 │ ' 131 ms' │ ' 20 ms' │ ' 13 ms' │ ' 1.54 x' │
1828
+ Array_Object_Unconstrained │ 1000000 │ ' 2821 ms' │ ' 62 ms' │ ' 45 ms' │ ' 1.38 x' │
1829
+ Array_Object_Constrained │ 1000000 │ ' 2958 ms' │ ' 119 ms' │ ' 134 ms' │ ' 0.89 x' │
1830
+ Array_Object_Recursive │ 1000000 │ ' 14695 ms' │ ' 1621 ms' │ ' 635 ms' │ ' 2.55 x' │
1831
+ Array_Tuple_Primitive │ 1000000 │ ' 478 ms' │ ' 35 ms' │ ' 28 ms' │ ' 1.25 x' │
1832
+ Array_Tuple_Object │ 1000000 │ ' 1623 ms' │ ' 63 ms' │ ' 48 ms' │ ' 1.31 x' │
1833
+ Array_Composite_Intersect │ 1000000 │ ' 1582 ms' │ ' 43 ms' │ ' 30 ms' │ ' 1.43 x' │
1834
+ Array_Composite_Union │ 1000000 │ ' 1331 ms' │ ' 76 ms' │ ' 40 ms' │ ' 1.90 x' │
1835
+ │ Array_Math_Vector4 │ 1000000 │ ' 564 ms' │ ' 38 ms' │ ' 24 ms' │ ' 1.58 x' │
1836
+ │ Array_Math_Matrix4 │ 1000000 │ ' 2382 ms' │ ' 111 ms' │ ' 83 ms' │ ' 1.34 x' │
1837
+ └────────────────────────────┴────────────┴──────────────┴──────────────┴──────────────┴──────────────┘
1838
+ ```
1839
+
1840
+ <a name='benchmark-compression'></a>
1841
+
1842
+ ### Compression
1843
+
1844
+ The following table lists esbuild compiled and minified sizes for each TypeBox module.
1845
+
1846
+ ```typescript
1847
+ ┌──────────────────────┬────────────┬────────────┬─────────────┐
1848
+ (index) Compiled Minified Compression
1849
+ ├──────────────────────┼────────────┼────────────┼─────────────┤
1850
+ │ typebox/compiler │ '122.4 kb' │ ' 53.4 kb' │ '2.29 x' │
1851
+ │ typebox/errors │ ' 67.6 kb' │ ' 29.6 kb' │ '2.28 x' │
1852
+ │ typebox/syntax │ '132.9 kb' │ ' 54.2 kb' │ '2.45 x' │
1853
+ │ typebox/system │ ' 7.4 kb' │ ' 3.2 kb' │ '2.33 x' │
1854
+ │ typebox/value │ '150.1 kb' │ ' 62.2 kb' │ '2.41 x' │
1855
+ │ typebox │ '106.8 kb' │ ' 43.2 kb' │ '2.47 x' │
1856
+ └──────────────────────┴────────────┴────────────┴─────────────┘
1857
+ ```
1858
+
1859
+ <a name='contribute'></a>
1860
+
1861
+ ## Contribute
1862
+
1863
+ TypeBox is open to community contribution. Please ensure you submit an open issue before submitting your pull request. The TypeBox project prefers open community discussion before accepting new features.