@sinclair/typebox 0.25.24 → 0.26.0-dev.1
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/compiler/compiler.d.ts +10 -5
- package/compiler/compiler.js +161 -123
- package/errors/errors.d.ts +56 -46
- package/errors/errors.js +234 -153
- package/package.json +1 -6
- package/readme.md +294 -207
- package/system/system.d.ts +9 -6
- package/system/system.js +17 -17
- package/typebox.d.ts +388 -162
- package/typebox.js +1716 -229
- package/value/cast.d.ts +2 -2
- package/value/cast.js +121 -188
- package/value/check.d.ts +1 -1
- package/value/check.js +156 -111
- package/value/convert.d.ts +13 -0
- package/value/convert.js +345 -0
- package/value/create.d.ts +6 -2
- package/value/create.js +149 -97
- package/{hash → value}/hash.js +39 -14
- package/value/index.d.ts +1 -0
- package/value/index.js +3 -1
- package/value/value.d.ts +2 -8
- package/value/value.js +20 -14
- package/conditional/conditional.d.ts +0 -17
- package/conditional/conditional.js +0 -91
- package/conditional/index.d.ts +0 -2
- package/conditional/index.js +0 -45
- package/conditional/structural.d.ts +0 -11
- package/conditional/structural.js +0 -685
- package/custom/custom.d.ts +0 -12
- package/custom/custom.js +0 -55
- package/custom/index.d.ts +0 -1
- package/custom/index.js +0 -44
- package/format/format.d.ts +0 -12
- package/format/format.js +0 -55
- package/format/index.d.ts +0 -1
- package/format/index.js +0 -44
- package/guard/extends.d.ts +0 -10
- package/guard/extends.js +0 -50
- package/guard/guard.d.ts +0 -60
- package/guard/guard.js +0 -440
- package/guard/index.d.ts +0 -2
- package/guard/index.js +0 -45
- package/hash/index.d.ts +0 -1
- package/hash/index.js +0 -44
- /package/{hash → value}/hash.d.ts +0 -0
package/readme.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<p>JSON Schema Type Builder with Static Type Resolution for TypeScript</p>
|
|
6
6
|
|
|
7
|
-
<img src="
|
|
7
|
+
<img src="./typebox.png" />
|
|
8
8
|
|
|
9
9
|
<br />
|
|
10
10
|
<br />
|
|
@@ -35,7 +35,7 @@ import { Static, Type } from 'npm:@sinclair/typebox'
|
|
|
35
35
|
import { Static, Type } from 'https://esm.sh/@sinclair/typebox'
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
##
|
|
38
|
+
## Example
|
|
39
39
|
|
|
40
40
|
```typescript
|
|
41
41
|
import { Static, Type } from '@sinclair/typebox'
|
|
@@ -62,32 +62,33 @@ type T = Static<typeof T> // type T = {
|
|
|
62
62
|
|
|
63
63
|
## Overview
|
|
64
64
|
|
|
65
|
-
TypeBox is a type builder
|
|
65
|
+
TypeBox is a runtime type builder that constructs in-memory JSON Schema objects that can be statically inferred as TypeScript types. The schemas produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox enables one to create a unified type that can be statically checked by TypeScript and runtime asserted using standard JSON Schema validation.
|
|
66
66
|
|
|
67
|
-
This library is designed to enable JSON schema to compose with the same flexibility as TypeScript's type system. It can be used
|
|
67
|
+
This library is designed to enable JSON schema to compose with the same flexibility as TypeScript's type system. It can be used as a simple tool to build up complex schemas or integrated into REST and RPC services to help validate data received over the wire.
|
|
68
68
|
|
|
69
69
|
License MIT
|
|
70
70
|
|
|
71
71
|
## Contents
|
|
72
72
|
- [Install](#install)
|
|
73
73
|
- [Overview](#overview)
|
|
74
|
-
- [
|
|
74
|
+
- [Usage](#usage)
|
|
75
75
|
- [Types](#types)
|
|
76
76
|
- [Standard](#types-standard)
|
|
77
77
|
- [Extended](#types-extended)
|
|
78
78
|
- [Modifiers](#types-modifiers)
|
|
79
79
|
- [Options](#types-options)
|
|
80
|
-
- [
|
|
80
|
+
- [Generics](#types-generics)
|
|
81
|
+
- [References](#types-references)
|
|
81
82
|
- [Recursive](#types-recursive)
|
|
82
|
-
- [Generic](#types-generic)
|
|
83
83
|
- [Conditional](#types-conditional)
|
|
84
|
-
- [Unsafe](#types-unsafe)
|
|
85
84
|
- [Guards](#types-guards)
|
|
85
|
+
- [Unsafe](#types-unsafe)
|
|
86
86
|
- [Strict](#types-strict)
|
|
87
87
|
- [Values](#values)
|
|
88
88
|
- [Create](#values-create)
|
|
89
89
|
- [Clone](#values-clone)
|
|
90
90
|
- [Check](#values-check)
|
|
91
|
+
- [Convert](#values-convert)
|
|
91
92
|
- [Cast](#values-cast)
|
|
92
93
|
- [Equal](#values-equal)
|
|
93
94
|
- [Hash](#values-hash)
|
|
@@ -101,20 +102,20 @@ License MIT
|
|
|
101
102
|
- [TypeSystem](#typecheck)
|
|
102
103
|
- [Types](#typesystem-types)
|
|
103
104
|
- [Formats](#typesystem-formats)
|
|
105
|
+
- [Policies](#typesystem-policies)
|
|
104
106
|
- [Benchmark](#benchmark)
|
|
105
107
|
- [Compile](#benchmark-compile)
|
|
106
108
|
- [Validate](#benchmark-validate)
|
|
107
109
|
- [Compression](#benchmark-compression)
|
|
108
110
|
- [Contribute](#contribute)
|
|
109
111
|
|
|
110
|
-
<a name="
|
|
112
|
+
<a name="usage"></a>
|
|
111
113
|
|
|
112
|
-
##
|
|
114
|
+
## Usage
|
|
113
115
|
|
|
114
|
-
The following
|
|
116
|
+
The following shows general usage.
|
|
115
117
|
|
|
116
118
|
```typescript
|
|
117
|
-
|
|
118
119
|
import { Static, Type } from '@sinclair/typebox'
|
|
119
120
|
|
|
120
121
|
//--------------------------------------------------------------------------------------------
|
|
@@ -173,9 +174,11 @@ type T = Static<typeof T> // type T = {
|
|
|
173
174
|
//
|
|
174
175
|
//--------------------------------------------------------------------------------------------
|
|
175
176
|
|
|
176
|
-
|
|
177
|
+
import { Value } from '@sinclair/typebox/value'
|
|
178
|
+
|
|
179
|
+
function receive(value: T) { // ... as a Static Type
|
|
177
180
|
|
|
178
|
-
if(
|
|
181
|
+
if(Value.Check(T, value)) { // ... as a JSON Schema
|
|
179
182
|
|
|
180
183
|
// ok...
|
|
181
184
|
}
|
|
@@ -186,13 +189,13 @@ function receive(value: T) { // ... as a Type
|
|
|
186
189
|
|
|
187
190
|
## Types
|
|
188
191
|
|
|
189
|
-
TypeBox
|
|
192
|
+
TypeBox types are small JSON schema fragments which can compose into more complex types though function composition. Each fragment is strictly defined to match to the static type checking rules of TypeScript. TypeBox provides a Standard type set which produces standards compliant JSON schema as well as an Extended type set used to define native JavaScript constructs.
|
|
190
193
|
|
|
191
194
|
<a name='types-standard'></a>
|
|
192
195
|
|
|
193
|
-
### Standard
|
|
196
|
+
### Standard Types
|
|
194
197
|
|
|
195
|
-
The following table lists the Standard TypeBox types.
|
|
198
|
+
The following table lists the Standard TypeBox types. These types are fully compatible with the JSON Schema specification.
|
|
196
199
|
|
|
197
200
|
```typescript
|
|
198
201
|
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
|
|
@@ -230,12 +233,6 @@ The following table lists the Standard TypeBox types.
|
|
|
230
233
|
│ │ │ } │
|
|
231
234
|
│ │ │ │
|
|
232
235
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
233
|
-
│ const T = Type.RegEx(/foo/) │ type T = string │ const T = { │
|
|
234
|
-
│ │ │ type: 'string', │
|
|
235
|
-
│ │ │ pattern: 'foo' │
|
|
236
|
-
│ │ │ } │
|
|
237
|
-
│ │ │ │
|
|
238
|
-
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
239
236
|
│ const T = Type.Literal(42) │ type T = 42 │ const T = { │
|
|
240
237
|
│ │ │ const: 42, │
|
|
241
238
|
│ │ │ type: 'number' │
|
|
@@ -252,15 +249,14 @@ The following table lists the Standard TypeBox types.
|
|
|
252
249
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
253
250
|
│ const T = Type.Object({ │ type T = { │ const T = { │
|
|
254
251
|
│ x: Type.Number(), │ x: number, │ type: 'object', │
|
|
255
|
-
│ y: Type.Number() │ y: number │
|
|
256
|
-
│ }) │ } │
|
|
257
|
-
│ │ │
|
|
258
|
-
│ │ │
|
|
259
|
-
│ │ │
|
|
260
|
-
│ │ │
|
|
261
|
-
│ │ │
|
|
262
|
-
│ │ │ }
|
|
263
|
-
│ │ │ required: ['x', 'y'] │
|
|
252
|
+
│ y: Type.Number() │ y: number │ required: ['x', 'y'], │
|
|
253
|
+
│ }) │ } │ properties: { │
|
|
254
|
+
│ │ │ x: { │
|
|
255
|
+
│ │ │ type: 'number' │
|
|
256
|
+
│ │ │ }, { │
|
|
257
|
+
│ │ │ type: 'number' │
|
|
258
|
+
│ │ │ } │
|
|
259
|
+
│ │ │ } │
|
|
264
260
|
│ │ │ } │
|
|
265
261
|
│ │ │ │
|
|
266
262
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
@@ -310,13 +306,36 @@ The following table lists the Standard TypeBox types.
|
|
|
310
306
|
│ │ │ │
|
|
311
307
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
312
308
|
│ const T = Type.Intersect([ │ type T = { │ const T = { │
|
|
313
|
-
│ Type.Object({ │ x: number │
|
|
314
|
-
│ x: Type.Number() │ } & { │
|
|
315
|
-
│ }), │ y: number │
|
|
316
|
-
│ Type.Object({ │ } │
|
|
317
|
-
│ y: Type.Number() │ │
|
|
318
|
-
│
|
|
319
|
-
│ ]) │ │
|
|
309
|
+
│ Type.Object({ │ x: number │ allOf: [{ │
|
|
310
|
+
│ x: Type.Number() │ } & { │ type: 'object', │
|
|
311
|
+
│ }), │ y: number │ required: ['x'], │
|
|
312
|
+
│ Type.Object({ │ } │ properties: { │
|
|
313
|
+
│ y: Type.Number() │ │ x: { │
|
|
314
|
+
│ ]) │ │ type: 'number' │
|
|
315
|
+
│ ]) │ │ } │
|
|
316
|
+
│ │ │ } │
|
|
317
|
+
│ │ │ }, { │
|
|
318
|
+
│ │ │ type: 'object', |
|
|
319
|
+
│ │ │ required: ['y'], │
|
|
320
|
+
│ │ │ properties: { │
|
|
321
|
+
│ │ │ y: { │
|
|
322
|
+
│ │ │ type: 'number' │
|
|
323
|
+
│ │ │ } │
|
|
324
|
+
│ │ │ }] │
|
|
325
|
+
│ │ │ } │
|
|
326
|
+
│ │ │ │
|
|
327
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
328
|
+
│ const T = Type.Composite([ │ type T = { │ const T = { │
|
|
329
|
+
│ Type.Object({ │ x: number | string │ type: 'object', │
|
|
330
|
+
│ x: Type.Number() │ y: number │ properties: { │
|
|
331
|
+
│ }), │ } │ x: { │
|
|
332
|
+
│ Type.Object({ │ │ anyOf: [ │
|
|
333
|
+
│ x: Type.String() │ │ { type: 'number' }, │
|
|
334
|
+
│ y: Type.Number() │ │ { type: 'string' } │
|
|
335
|
+
│ }) │ │ ] │
|
|
336
|
+
│ ]) │ │ }, │
|
|
337
|
+
│ │ │ y: { │
|
|
338
|
+
│ │ │ type: 'number' │
|
|
320
339
|
│ │ │ } │
|
|
321
340
|
│ │ │ }, │
|
|
322
341
|
│ │ │ required: ['x', 'y'] │
|
|
@@ -334,6 +353,47 @@ The following table lists the Standard TypeBox types.
|
|
|
334
353
|
│ │ │ } │
|
|
335
354
|
│ │ │ │
|
|
336
355
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
356
|
+
│ const T = Type.Not( | type T = string │ const T = { │
|
|
357
|
+
| Type.Union([ │ │ allOf: [{ │
|
|
358
|
+
│ Type.Literal('x'), │ │ not: { │
|
|
359
|
+
│ Type.Literal('y'), │ │ anyOf: [ │
|
|
360
|
+
│ Type.Literal('z') │ │ { const: 'x' }, │
|
|
361
|
+
│ ]), │ │ { const: 'y' }, │
|
|
362
|
+
│ Type.String() │ │ { const: 'z' } │
|
|
363
|
+
│ ) │ │ ] │
|
|
364
|
+
│ │ │ } │
|
|
365
|
+
│ │ │ }, { │
|
|
366
|
+
│ │ │ type: 'string' │
|
|
367
|
+
│ │ │ }] │
|
|
368
|
+
│ │ │ } │
|
|
369
|
+
│ │ │ │
|
|
370
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
371
|
+
│ const T = Type.Extends( │ type T = │ const T = { │
|
|
372
|
+
│ Type.String(), │ string extends number │ const: false, │
|
|
373
|
+
│ Type.Number(), │ true : false │ type: 'boolean' │
|
|
374
|
+
│ Type.Literal(true), │ │ } │
|
|
375
|
+
│ Type.Literal(false) │ │ │
|
|
376
|
+
│ ) │ │ │
|
|
377
|
+
│ │ │ │
|
|
378
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
379
|
+
│ const T = Type.Extract( │ type T = Extract< │ const T = { │
|
|
380
|
+
│ Type.Union([ │ string | number, │ type: 'string' │
|
|
381
|
+
│ Type.String(), │ string │ } │
|
|
382
|
+
│ Type.Number(), │ > │ │
|
|
383
|
+
│ ]), │ │ │
|
|
384
|
+
│ Type.String() │ │ │
|
|
385
|
+
│ ) │ │ │
|
|
386
|
+
│ │ │ │
|
|
387
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
388
|
+
│ const T = Type.Exclude( │ type T = Exclude< │ const T = { │
|
|
389
|
+
│ Type.Union([ │ string | number, │ type: 'number' │
|
|
390
|
+
│ Type.String(), │ string │ } │
|
|
391
|
+
│ Type.Number(), │ > │ │
|
|
392
|
+
│ ]), │ │ │
|
|
393
|
+
│ Type.String() │ │ │
|
|
394
|
+
│ ) │ │ │
|
|
395
|
+
│ │ │ │
|
|
396
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
337
397
|
│ const T = Type.Record( │ type T = Record< │ const T = { │
|
|
338
398
|
│ Type.String(), │ string, │ type: 'object', │
|
|
339
399
|
│ Type.Number() │ number, │ patternProperties: { │
|
|
@@ -359,15 +419,15 @@ The following table lists the Standard TypeBox types.
|
|
|
359
419
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
360
420
|
│ const T = Type.Required( │ type T = Required<{ │ const T = { │
|
|
361
421
|
│ Type.Object({ │ x?: number, │ type: 'object', │
|
|
362
|
-
│ x: Type.Optional( │ y?: number │
|
|
363
|
-
│ Type.Number() | }> │
|
|
364
|
-
│ ), │ │
|
|
365
|
-
│ y: Type.Optional( │ │
|
|
366
|
-
│ Type.Number() │ │
|
|
367
|
-
│ ) │ │
|
|
368
|
-
│ }) │ │
|
|
369
|
-
│ ) │ │
|
|
370
|
-
│ │ │
|
|
422
|
+
│ x: Type.Optional( │ y?: number │ required: ['x', 'y'], │
|
|
423
|
+
│ Type.Number() | }> │ properties: { │
|
|
424
|
+
│ ), │ │ x: { │
|
|
425
|
+
│ y: Type.Optional( │ │ type: 'number' │
|
|
426
|
+
│ Type.Number() │ │ }, │
|
|
427
|
+
│ ) │ │ y: { │
|
|
428
|
+
│ }) │ │ type: 'number' │
|
|
429
|
+
│ ) │ │ } │
|
|
430
|
+
│ │ │ } │
|
|
371
431
|
│ │ │ } │
|
|
372
432
|
│ │ │ │
|
|
373
433
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
@@ -392,14 +452,38 @@ The following table lists the Standard TypeBox types.
|
|
|
392
452
|
│ │ │ required: ['y'] │
|
|
393
453
|
│ │ │ } │
|
|
394
454
|
│ │ │ │
|
|
455
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
456
|
+
│ const A = Type.Object({ │ type A = { │ const T = { │
|
|
457
|
+
│ x: Type.Number(), │ x: number, │ $ref: 'A' │
|
|
458
|
+
│ y: Type.Number() │ y: number │ } │
|
|
459
|
+
│ }, { $id: 'T' }) | } │ │
|
|
460
|
+
│ │ │ │
|
|
461
|
+
│ const T = Type.Ref(A) │ type T = A │ │
|
|
462
|
+
│ │ │ │
|
|
463
|
+
│ │ │ │
|
|
464
|
+
│ │ │ │
|
|
465
|
+
│ │ │ │
|
|
466
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
467
|
+
│ const A = Type.Object({ │ type T = { │ const T = { │
|
|
468
|
+
│ x: Type.Number(), │ x: number, │ $id: 'T' │
|
|
469
|
+
│ y: Type.Number() │ y: number │ type: 'object', │
|
|
470
|
+
│ }, { $id: 'T' }) | } │ required: ['x', 'y'], │
|
|
471
|
+
│ │ │ properties: { │
|
|
472
|
+
│ const T = Type.Deref( │ │ x: { type: 'number' }, │
|
|
473
|
+
│ Type.Ref(A) │ │ y: { type: 'number' }, │
|
|
474
|
+
│ ) │ │ } │
|
|
475
|
+
│ │ │ } │
|
|
476
|
+
│ │ │ │
|
|
395
477
|
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
396
478
|
```
|
|
397
479
|
|
|
398
480
|
<a name='types-extended'></a>
|
|
399
481
|
|
|
400
|
-
### Extended
|
|
482
|
+
### Extended Types
|
|
483
|
+
|
|
484
|
+
TypeBox provides several extended types that can be used to produce schematics for common JavaScript constructs. These types cannot be used with standard JSON schema validators; but are useful to help frame schematics for RPC interfaces that may receive JSON validated data. Extended types are prefixed with the `[Extended]` doc comment for convenience.
|
|
401
485
|
|
|
402
|
-
|
|
486
|
+
The following lists the supported types
|
|
403
487
|
|
|
404
488
|
```typescript
|
|
405
489
|
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
|
|
@@ -462,6 +546,24 @@ TypeBox provides a set of extended types that can be used to express schematics
|
|
|
462
546
|
│ │ │ } │
|
|
463
547
|
│ │ │ │
|
|
464
548
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
549
|
+
│ const T = Type.RegEx(/foo/) │ type T = string │ const T = { │
|
|
550
|
+
│ │ │ type: 'string', │
|
|
551
|
+
│ │ │ pattern: 'foo' │
|
|
552
|
+
│ │ │ } │
|
|
553
|
+
│ │ │ │
|
|
554
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
555
|
+
│ const T = Type.Symbol() │ type T = symbol │ const T = { │
|
|
556
|
+
│ │ │ type: 'null', │
|
|
557
|
+
│ │ │ typeOf: 'Symbol' │
|
|
558
|
+
│ │ │ } │
|
|
559
|
+
│ │ │ │
|
|
560
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
561
|
+
│ const T = Type.BigInt() │ type T = bigint │ const T = { │
|
|
562
|
+
│ │ │ type: 'null', │
|
|
563
|
+
│ │ │ typeOf: 'BigInt' │
|
|
564
|
+
│ │ │ } │
|
|
565
|
+
│ │ │ │
|
|
566
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
465
567
|
│ const T = Type.Void() │ type T = void │ const T = { │
|
|
466
568
|
│ │ │ type: 'null' │
|
|
467
569
|
│ │ │ typeOf: 'Void' │
|
|
@@ -474,7 +576,7 @@ TypeBox provides a set of extended types that can be used to express schematics
|
|
|
474
576
|
|
|
475
577
|
### Modifiers
|
|
476
578
|
|
|
477
|
-
TypeBox provides
|
|
579
|
+
TypeBox provides property modifier types that allow properties to be mapped with TypeScript `readonly` and `optional`. The following table shows the modifier types and how they map between TypeScript and JSON Schema.
|
|
478
580
|
|
|
479
581
|
```typescript
|
|
480
582
|
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
|
|
@@ -518,24 +620,69 @@ TypeBox provides modifiers that can be applied to an objects properties. This al
|
|
|
518
620
|
|
|
519
621
|
### Options
|
|
520
622
|
|
|
521
|
-
You can pass
|
|
623
|
+
You can pass JSON Schema compliant options on the last argument of any type. Option property hints are provided for convenience.
|
|
522
624
|
|
|
523
625
|
```typescript
|
|
524
|
-
//
|
|
525
|
-
const T = Type.String({
|
|
626
|
+
// String must be an email
|
|
627
|
+
const T = Type.String({ // const T = {
|
|
628
|
+
format: 'email' // type: 'string',
|
|
629
|
+
}) // format: 'email'
|
|
630
|
+
// }
|
|
631
|
+
|
|
632
|
+
// Mumber must be a multiple of 2
|
|
633
|
+
const T = Type.Number({ // const T = {
|
|
634
|
+
multipleOf: 2 // type: 'number',
|
|
635
|
+
}) // multipleOf: 2
|
|
636
|
+
// }
|
|
637
|
+
|
|
638
|
+
// Array must have at least 5 integer values
|
|
639
|
+
const T = Type.Array(Type.Integer(), { // const T = {
|
|
640
|
+
minItems: 5 // type: 'array',
|
|
641
|
+
}) // minItems: 5,
|
|
642
|
+
// items: {
|
|
643
|
+
// type: 'integer'
|
|
644
|
+
// }
|
|
645
|
+
// }
|
|
646
|
+
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
<a name='types-generics'></a>
|
|
650
|
+
|
|
651
|
+
### Generic Types
|
|
652
|
+
|
|
653
|
+
Generic types can be created with generic functions. The following creates a generic `Vector<T>` type.
|
|
654
|
+
|
|
655
|
+
```typescript
|
|
656
|
+
import { Type, Static, TSchema } from '@sinclair/typebox'
|
|
657
|
+
|
|
658
|
+
const Vector = <T extends TSchema>(t: T) => Type.Object({ x: t, y: t, z: t })
|
|
526
659
|
|
|
527
|
-
|
|
528
|
-
|
|
660
|
+
const NumberVector = Vector(Type.Number()) // const NumberVector = {
|
|
661
|
+
// type: 'object',
|
|
662
|
+
// required: ['x', 'y', 'z'],
|
|
663
|
+
// properties: {
|
|
664
|
+
// x: { type: 'number' },
|
|
665
|
+
// y: { type: 'number' },
|
|
666
|
+
// z: { type: 'number' }
|
|
667
|
+
// }
|
|
668
|
+
// }
|
|
529
669
|
|
|
530
|
-
|
|
531
|
-
|
|
670
|
+
const BooleanVector = Vector(Type.Boolean()) // const BooleanVector = {
|
|
671
|
+
// type: 'object',
|
|
672
|
+
// required: ['x', 'y', 'z'],
|
|
673
|
+
// properties: {
|
|
674
|
+
// x: { type: 'boolean' },
|
|
675
|
+
// y: { type: 'boolean' },
|
|
676
|
+
// z: { type: 'boolean' }
|
|
677
|
+
// }
|
|
678
|
+
// }
|
|
532
679
|
```
|
|
533
680
|
|
|
534
|
-
<a name='types-
|
|
681
|
+
<a name='types-references'></a>
|
|
535
682
|
|
|
536
|
-
### Reference
|
|
683
|
+
### Reference Types
|
|
537
684
|
|
|
538
|
-
|
|
685
|
+
Reference types are supported with `Type.Ref(...)`. Use `Type.Deref(...)` to dereference a type.
|
|
539
686
|
|
|
540
687
|
```typescript
|
|
541
688
|
const T = Type.String({ $id: 'T' }) // const T = {
|
|
@@ -546,13 +693,18 @@ const T = Type.String({ $id: 'T' }) // const T = {
|
|
|
546
693
|
const R = Type.Ref(T) // const R = {
|
|
547
694
|
// $ref: 'T'
|
|
548
695
|
// }
|
|
696
|
+
|
|
697
|
+
const U = Type.Deref(R) // const U = {
|
|
698
|
+
// $id: 'T',
|
|
699
|
+
// type: 'string'
|
|
700
|
+
// }
|
|
549
701
|
```
|
|
550
702
|
|
|
551
703
|
<a name='types-recursive'></a>
|
|
552
704
|
|
|
553
|
-
### Recursive
|
|
705
|
+
### Recursive Types
|
|
554
706
|
|
|
555
|
-
|
|
707
|
+
Recursive types are supported with `Type.Recursive(...)`.
|
|
556
708
|
|
|
557
709
|
```typescript
|
|
558
710
|
const Node = Type.Recursive(Node => Type.Object({ // const Node = {
|
|
@@ -581,95 +733,34 @@ type Node = Static<typeof Node> // type Node = {
|
|
|
581
733
|
// }
|
|
582
734
|
|
|
583
735
|
function test(node: Node) {
|
|
584
|
-
const id = node.nodes[0].nodes[0]
|
|
585
|
-
.nodes[0].nodes[0]
|
|
586
|
-
.id
|
|
736
|
+
const id = node.nodes[0].nodes[0].id // id is string
|
|
587
737
|
}
|
|
588
738
|
```
|
|
589
739
|
|
|
590
|
-
<a name='types-generic'></a>
|
|
591
|
-
|
|
592
|
-
### Generic
|
|
593
|
-
|
|
594
|
-
Use functions to create generic types. The following creates a generic `Nullable<T>` type.
|
|
595
|
-
|
|
596
|
-
```typescript
|
|
597
|
-
import { Type, Static, TSchema } from '@sinclair/typebox'
|
|
598
|
-
|
|
599
|
-
const Nullable = <T extends TSchema>(type: T) => Type.Union([type, Type.Null()])
|
|
600
|
-
|
|
601
|
-
const T = Nullable(Type.String()) // const T = {
|
|
602
|
-
// anyOf: [{
|
|
603
|
-
// type: 'string'
|
|
604
|
-
// }, {
|
|
605
|
-
// type: 'null'
|
|
606
|
-
// }]
|
|
607
|
-
// }
|
|
608
|
-
|
|
609
|
-
type T = Static<typeof T> // type T = string | null
|
|
610
|
-
|
|
611
|
-
const U = Nullable(Type.Number()) // const U = {
|
|
612
|
-
// anyOf: [{
|
|
613
|
-
// type: 'number'
|
|
614
|
-
// }, {
|
|
615
|
-
// type: 'null'
|
|
616
|
-
// }]
|
|
617
|
-
// }
|
|
618
|
-
|
|
619
|
-
type U = Static<typeof U> // type U = number | null
|
|
620
|
-
```
|
|
621
|
-
|
|
622
740
|
<a name='types-conditional'></a>
|
|
623
741
|
|
|
624
|
-
### Conditional
|
|
742
|
+
### Conditional Types
|
|
625
743
|
|
|
626
|
-
|
|
744
|
+
Conditional types are supported with `Extends`, `Exclude` and `Extract`. These work the same as in TypeScript.
|
|
627
745
|
|
|
628
|
-
|
|
746
|
+
#### TypeScript
|
|
629
747
|
|
|
630
748
|
```typescript
|
|
631
|
-
|
|
749
|
+
type T0 = string extends number ? true : false
|
|
750
|
+
// ^ false
|
|
751
|
+
type T1 = Extract<string | number, number>
|
|
752
|
+
// ^ number
|
|
753
|
+
type T2 = Exclude<string | number, number>
|
|
754
|
+
// ^ string
|
|
632
755
|
```
|
|
633
|
-
|
|
634
|
-
|
|
756
|
+
#### TypeBox
|
|
635
757
|
```typescript
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
│ Type.Number(), │ true : false │ type: 'boolean' │
|
|
643
|
-
│ Type.Literal(true), │ │ } │
|
|
644
|
-
│ Type.Literal(false) │ │ │
|
|
645
|
-
│ ) │ │ │
|
|
646
|
-
│ │ │ │
|
|
647
|
-
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
648
|
-
│ const T = Conditional.Extract( │ type T = Extract< │ const T = { │
|
|
649
|
-
│ Type.Union([ │ 'a' | 'b' | 'c', │ anyOf: [{ │
|
|
650
|
-
│ Type.Literal('a'), │ 'a' | 'f' │ const: 'a' │
|
|
651
|
-
│ Type.Literal('b'), │ > │ type: 'string' │
|
|
652
|
-
│ Type.Literal('c') │ │ }] │
|
|
653
|
-
│ ]), │ │ } │
|
|
654
|
-
│ Type.Union([ │ │ │
|
|
655
|
-
│ Type.Literal('a'), │ │ │
|
|
656
|
-
│ Type.Literal('f') │ │ │
|
|
657
|
-
│ ]) │ │ │
|
|
658
|
-
│ ) │ │ │
|
|
659
|
-
│ │ │ │
|
|
660
|
-
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
661
|
-
│ const T = Conditional.Exclude( │ type T = Exclude< │ const T = { │
|
|
662
|
-
│ Type.Union([ │ 'a' | 'b' | 'c', │ anyOf: [{ │
|
|
663
|
-
│ Type.Literal('a'), │ 'a' │ const: 'b', │
|
|
664
|
-
│ Type.Literal('b'), │ > │ type: 'string' │
|
|
665
|
-
│ Type.Literal('c') │ │ }, { │
|
|
666
|
-
│ ]), │ │ const: 'c', │
|
|
667
|
-
│ Type.Union([ │ │ type: 'string' │
|
|
668
|
-
│ Type.Literal('a') │ │ }] │
|
|
669
|
-
│ ]) │ │ } │
|
|
670
|
-
│ ) │ │ │
|
|
671
|
-
│ │ │ │
|
|
672
|
-
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
758
|
+
const T0 = Type.Extends(Type.String(), Type.Number(), Type.Literal(true), Type.Literal(false))
|
|
759
|
+
// ^ TLiteral<false>
|
|
760
|
+
const T1 = Type.Extract(Type.Union([Type.String(), Type.Number()]), Type.Number())
|
|
761
|
+
// ^ TNumber
|
|
762
|
+
const T2 = Type.Exclude(Type.Union([Type.String(), Type.Number()]), Type.Number())
|
|
763
|
+
// ^ TString<string>
|
|
673
764
|
```
|
|
674
765
|
|
|
675
766
|
<a name='types-unsafe'></a>
|
|
@@ -686,16 +777,12 @@ const T = Type.Unsafe<string>({ type: 'number' }) // const T = {
|
|
|
686
777
|
type T = Static<typeof T> // type T = string
|
|
687
778
|
```
|
|
688
779
|
|
|
689
|
-
|
|
780
|
+
The `Type.Unsafe(...)` type allows for the expression of specific OpenAPI schema representations.
|
|
690
781
|
|
|
691
782
|
```typescript
|
|
692
783
|
import { Type, Static, TSchema } from '@sinclair/typebox'
|
|
693
784
|
|
|
694
|
-
//--------------------------------------------------------------------------------------------
|
|
695
|
-
//
|
|
696
785
|
// Nullable<T>
|
|
697
|
-
//
|
|
698
|
-
//--------------------------------------------------------------------------------------------
|
|
699
786
|
|
|
700
787
|
function Nullable<T extends TSchema>(schema: T) {
|
|
701
788
|
return Type.Unsafe<Static<T> | null>({ ...schema, nullable: true })
|
|
@@ -708,12 +795,7 @@ const T = Nullable(Type.String()) // const T = {
|
|
|
708
795
|
|
|
709
796
|
type T = Static<typeof T> // type T = string | null
|
|
710
797
|
|
|
711
|
-
|
|
712
|
-
//--------------------------------------------------------------------------------------------
|
|
713
|
-
//
|
|
714
798
|
// StringEnum<string[]>
|
|
715
|
-
//
|
|
716
|
-
//--------------------------------------------------------------------------------------------
|
|
717
799
|
|
|
718
800
|
function StringEnum<T extends string[]>(values: [...T]) {
|
|
719
801
|
return Type.Unsafe<T[number]>({ type: 'string', enum: values })
|
|
@@ -730,10 +812,10 @@ type T = Static<typeof T> // type T = 'A' | 'B' | 'C'
|
|
|
730
812
|
|
|
731
813
|
### Guards
|
|
732
814
|
|
|
733
|
-
|
|
815
|
+
TypeBox provides a `TypeGuard` module for reflection and type assertion.
|
|
734
816
|
|
|
735
817
|
```typescript
|
|
736
|
-
import { TypeGuard } from '@sinclair/typebox
|
|
818
|
+
import { Type, TypeGuard } from '@sinclair/typebox'
|
|
737
819
|
|
|
738
820
|
const T = Type.String()
|
|
739
821
|
|
|
@@ -747,7 +829,7 @@ if(TypeGuard.TString(T)) {
|
|
|
747
829
|
|
|
748
830
|
### Strict
|
|
749
831
|
|
|
750
|
-
TypeBox schemas contain the `Kind` and `Modifier` symbol properties. These properties are
|
|
832
|
+
TypeBox schemas contain the `Kind` and `Modifier` symbol properties. These properties are used for type composition and runtime type reflection. These properties are not strictly valid JSON schema; so in some cases it may be desirable to omit them. TypeBox provides a `Type.Strict()` function that will omit these properties if necessary.
|
|
751
833
|
|
|
752
834
|
```typescript
|
|
753
835
|
const T = Type.Object({ // const T = {
|
|
@@ -776,7 +858,7 @@ const U = Type.Strict(T) // const U = {
|
|
|
776
858
|
|
|
777
859
|
## Values
|
|
778
860
|
|
|
779
|
-
TypeBox
|
|
861
|
+
TypeBox provides an optional utility module that can be used to perform common operations on JavaScript values. This module includes functionality to create, check and cast values from types as well as check equality, clone, diff and patch JavaScript values. This module is provided via additional import.
|
|
780
862
|
|
|
781
863
|
```typescript
|
|
782
864
|
import { Value } from '@sinclair/typebox/value'
|
|
@@ -786,7 +868,7 @@ import { Value } from '@sinclair/typebox/value'
|
|
|
786
868
|
|
|
787
869
|
### Create
|
|
788
870
|
|
|
789
|
-
Use the Create function to create a value from a
|
|
871
|
+
Use the Create function to create a value from a type. TypeBox will use default values if specified.
|
|
790
872
|
|
|
791
873
|
```typescript
|
|
792
874
|
const T = Type.Object({ x: Type.Number(), y: Type.Number({ default: 42 }) })
|
|
@@ -816,6 +898,20 @@ const T = Type.Object({ x: Type.Number() })
|
|
|
816
898
|
const R = Value.Check(T, { x: 1 }) // const R = true
|
|
817
899
|
```
|
|
818
900
|
|
|
901
|
+
<a name='values-convert'></a>
|
|
902
|
+
|
|
903
|
+
### Convert
|
|
904
|
+
|
|
905
|
+
Use the Convert function to convert a value into its target type if a reasonable conversion is possible.
|
|
906
|
+
|
|
907
|
+
```typescript
|
|
908
|
+
const T = Type.Object({ x: Type.Number(), y: Type.Number() })
|
|
909
|
+
|
|
910
|
+
const R1 = Value.Convert(T, { x: '3.14' }) // const R1 = { x: 3.14 }
|
|
911
|
+
|
|
912
|
+
const R2 = Value.Convert(T, { x: 'not a number' }) // const R2 = { x: 'not a number' }
|
|
913
|
+
```
|
|
914
|
+
|
|
819
915
|
<a name='values-cast'></a>
|
|
820
916
|
|
|
821
917
|
### Cast
|
|
@@ -918,7 +1014,7 @@ const R = [...Value.Errors(T, { x: '42' })] // const R = [{
|
|
|
918
1014
|
|
|
919
1015
|
### Pointer
|
|
920
1016
|
|
|
921
|
-
Use ValuePointer to perform mutable updates on existing values using [RFC6901](https://www.rfc-editor.org/rfc/rfc6901)
|
|
1017
|
+
Use ValuePointer to perform mutable updates on existing values using [RFC6901](https://www.rfc-editor.org/rfc/rfc6901) JSON Pointers.
|
|
922
1018
|
|
|
923
1019
|
```typescript
|
|
924
1020
|
import { ValuePointer } from '@sinclair/typebox/value'
|
|
@@ -933,15 +1029,15 @@ ValuePointer.Set(A, '/z', 1) // const A = { x: 1, y: 1,
|
|
|
933
1029
|
|
|
934
1030
|
## TypeCheck
|
|
935
1031
|
|
|
936
|
-
TypeBox
|
|
1032
|
+
TypeBox types target JSON Schema draft 6 so are compatible with any validator that supports this specification. TypeBox also provides a built in type checking compiler designed specifically for high performance compilation and value assertion.
|
|
937
1033
|
|
|
938
|
-
The following sections detail using
|
|
1034
|
+
The following sections detail using Ajv and TypeBox's compiler infrastructure.
|
|
939
1035
|
|
|
940
1036
|
<a name='typecheck-ajv'></a>
|
|
941
1037
|
|
|
942
1038
|
## Ajv
|
|
943
1039
|
|
|
944
|
-
The following shows the recommended setup for Ajv.
|
|
1040
|
+
The following shows the recommended setup for Ajv.
|
|
945
1041
|
|
|
946
1042
|
```bash
|
|
947
1043
|
$ npm install ajv ajv-formats --save
|
|
@@ -982,7 +1078,7 @@ const R = C({ x: 1, y: 2, z: 3 }) // const R = true
|
|
|
982
1078
|
|
|
983
1079
|
### TypeCompiler
|
|
984
1080
|
|
|
985
|
-
The TypeCompiler is a
|
|
1081
|
+
The TypeBox TypeCompiler is a high performance JIT 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 designed to serve as a validation backend that can be integrated into larger applications; but can also be used as a general purpose validator.
|
|
986
1082
|
|
|
987
1083
|
The TypeCompiler is provided as an optional import.
|
|
988
1084
|
|
|
@@ -1002,7 +1098,7 @@ const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck<TObje
|
|
|
1002
1098
|
const R = C.Check({ x: 1, y: 2, z: 3 }) // const R = true
|
|
1003
1099
|
```
|
|
1004
1100
|
|
|
1005
|
-
Use `Errors(...)` to
|
|
1101
|
+
Use the `Errors(...)` function to produce diagnostic errors for a value. The `Errors(...)` function will return an iterator that if enumerated; will perform an exhaustive check across the entire value and yield any error found. For performance, this function should only be called after failed `Check(...)`. Applications may also choose to yield only the first value to avoid exhaustive error generation.
|
|
1006
1102
|
|
|
1007
1103
|
```typescript
|
|
1008
1104
|
const C = TypeCompiler.Compile(Type.Object({ // const C: TypeCheck<TObject<{
|
|
@@ -1047,7 +1143,7 @@ console.log(C.Code()) // return function check(va
|
|
|
1047
1143
|
|
|
1048
1144
|
## TypeSystem
|
|
1049
1145
|
|
|
1050
|
-
TypeBox
|
|
1146
|
+
The TypeBox TypeSystem module provides functionality to define types above and beyond the Standard and Extended type sets as well as control various assertion polices. Configurations made to the TypeSystem module are observed by both `TypeCompiler` and `Value` modules.
|
|
1051
1147
|
|
|
1052
1148
|
The TypeSystem module is provided as an optional import.
|
|
1053
1149
|
|
|
@@ -1059,71 +1155,62 @@ import { TypeSystem } from '@sinclair/typebox/system'
|
|
|
1059
1155
|
|
|
1060
1156
|
### Types
|
|
1061
1157
|
|
|
1062
|
-
Use the `
|
|
1158
|
+
Use the `Type(...)` function to create a custom type. This function will return a type factory function that can be used to construct the type. The following creates a Point type.
|
|
1063
1159
|
|
|
1064
1160
|
```typescript
|
|
1065
|
-
|
|
1066
|
-
//
|
|
1067
|
-
// Use TypeSystem.CreateType(...) to define and return a type factory function
|
|
1068
|
-
//
|
|
1069
|
-
//--------------------------------------------------------------------------------------------
|
|
1161
|
+
type PointOptions = { } // The Type Options
|
|
1070
1162
|
|
|
1071
|
-
type
|
|
1163
|
+
type PointType = { x: number, y: number } // The Static<T> Type
|
|
1072
1164
|
|
|
1073
|
-
const
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
}
|
|
1081
|
-
)
|
|
1165
|
+
const Point = TypeSystem.Type<PointType, PointOptions>('Point', (options, value) => {
|
|
1166
|
+
return (
|
|
1167
|
+
typeof value === 'object' && value !== null &&
|
|
1168
|
+
typeof value.x === 'number' &&
|
|
1169
|
+
typeof value.y === 'number'
|
|
1170
|
+
)
|
|
1171
|
+
})
|
|
1082
1172
|
|
|
1083
|
-
|
|
1084
|
-
//
|
|
1085
|
-
// Use the custom type like any other type
|
|
1086
|
-
//
|
|
1087
|
-
//--------------------------------------------------------------------------------------------
|
|
1173
|
+
const T = Point()
|
|
1088
1174
|
|
|
1089
|
-
|
|
1090
|
-
// minimum: 10n,
|
|
1091
|
-
// maximum: 20n,
|
|
1092
|
-
// [Symbol(TypeBox.Kind)]: 'BigNumber'
|
|
1093
|
-
// }
|
|
1175
|
+
type T = Static<typeof T> // type T = { x: number, y: number }
|
|
1094
1176
|
|
|
1095
|
-
const
|
|
1096
|
-
const X = C.Check(15n) // const X = true
|
|
1097
|
-
const Y = C.Check(5n) // const Y = false
|
|
1098
|
-
const Z = C.Check(25n) // const Z = false
|
|
1177
|
+
const R = Value.Check(T, { x: 1, y: 2 }) // const R = true
|
|
1099
1178
|
```
|
|
1100
1179
|
|
|
1101
1180
|
<a name='typesystem-formats'></a>
|
|
1102
1181
|
|
|
1103
1182
|
### Formats
|
|
1104
1183
|
|
|
1105
|
-
Use the `
|
|
1184
|
+
Use the `Format(...)` function to create a custom string format. The following creates a custom string format that checks for lowercase strings.
|
|
1106
1185
|
|
|
1107
1186
|
```typescript
|
|
1108
|
-
|
|
1109
|
-
//
|
|
1110
|
-
// Use TypeSystem.CreateFormat(...) to define a custom string format
|
|
1111
|
-
//
|
|
1112
|
-
//--------------------------------------------------------------------------------------------
|
|
1187
|
+
TypeSystem.Format('lowercase', value => value === value.toLowerCase()) // format should be lowercase
|
|
1113
1188
|
|
|
1114
|
-
|
|
1189
|
+
const T = Type.String({ format: 'lowercase' })
|
|
1115
1190
|
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1191
|
+
const A = Value.Check(T, 'action') // const A = true
|
|
1192
|
+
|
|
1193
|
+
const B = Value.Check(T, 'ACTION') // const B = false
|
|
1194
|
+
```
|
|
1195
|
+
|
|
1196
|
+
<a name='typesystem-policies'></a>
|
|
1197
|
+
|
|
1198
|
+
### Policies
|
|
1199
|
+
|
|
1200
|
+
TypeBox validates using JSON Schema assertion policies by default. It is possible to override these policies and have TypeBox assert using TypeScript policies. The following overrides are available.
|
|
1201
|
+
|
|
1202
|
+
```typescript
|
|
1203
|
+
// Allow arrays to validate as object types (default is false)
|
|
1119
1204
|
//
|
|
1120
|
-
|
|
1205
|
+
// const A: {} = [] - allowed in TS
|
|
1121
1206
|
|
|
1122
|
-
|
|
1207
|
+
TypeSystem.AllowArrayObjects = true
|
|
1123
1208
|
|
|
1124
|
-
|
|
1209
|
+
// Allow numeric values to be NaN or + or - Infinity (default is false)
|
|
1210
|
+
//
|
|
1211
|
+
// const A: number = NaN - allowed in TS
|
|
1125
1212
|
|
|
1126
|
-
|
|
1213
|
+
TypeSystem.AllowNaN = true
|
|
1127
1214
|
```
|
|
1128
1215
|
|
|
1129
1216
|
<a name='benchmark'></a>
|