@sinclair/typebox 0.25.24 → 0.26.0-dev

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.
Files changed (46) hide show
  1. package/compiler/compiler.d.ts +9 -4
  2. package/compiler/compiler.js +160 -122
  3. package/errors/errors.d.ts +56 -46
  4. package/errors/errors.js +234 -153
  5. package/package.json +1 -6
  6. package/readme.md +294 -207
  7. package/system/system.d.ts +9 -6
  8. package/system/system.js +17 -17
  9. package/typebox.d.ts +386 -162
  10. package/typebox.js +1710 -229
  11. package/value/cast.d.ts +2 -2
  12. package/value/cast.js +121 -188
  13. package/value/check.d.ts +1 -1
  14. package/value/check.js +156 -111
  15. package/value/convert.d.ts +13 -0
  16. package/value/convert.js +345 -0
  17. package/value/create.d.ts +6 -2
  18. package/value/create.js +149 -97
  19. package/{hash → value}/hash.js +39 -14
  20. package/value/index.d.ts +1 -0
  21. package/value/index.js +3 -1
  22. package/value/value.d.ts +2 -8
  23. package/value/value.js +20 -14
  24. package/conditional/conditional.d.ts +0 -17
  25. package/conditional/conditional.js +0 -91
  26. package/conditional/index.d.ts +0 -2
  27. package/conditional/index.js +0 -45
  28. package/conditional/structural.d.ts +0 -11
  29. package/conditional/structural.js +0 -685
  30. package/custom/custom.d.ts +0 -12
  31. package/custom/custom.js +0 -55
  32. package/custom/index.d.ts +0 -1
  33. package/custom/index.js +0 -44
  34. package/format/format.d.ts +0 -12
  35. package/format/format.js +0 -55
  36. package/format/index.d.ts +0 -1
  37. package/format/index.js +0 -44
  38. package/guard/extends.d.ts +0 -10
  39. package/guard/extends.js +0 -50
  40. package/guard/guard.d.ts +0 -60
  41. package/guard/guard.js +0 -440
  42. package/guard/index.d.ts +0 -2
  43. package/guard/index.js +0 -45
  44. package/hash/index.d.ts +0 -1
  45. package/hash/index.js +0 -44
  46. /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="https://github.com/sinclairzx81/typebox/blob/master/typebox.png?raw=true" />
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
- ## Usage
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 library that creates 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.
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 either as a simple tool to build up complex schemas or integrated into REST and RPC services to help validate data received over the wire.
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
- - [Example](#Example)
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
- - [Reference](#types-reference)
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="Example"></a>
112
+ <a name="usage"></a>
111
113
 
112
- ## Example
114
+ ## Usage
113
115
 
114
- The following demonstrates TypeBox's general usage.
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
- function receive(value: T) { // ... as a Type
177
+ import { Value } from '@sinclair/typebox/value'
178
+
179
+ function receive(value: T) { // ... as a Static Type
177
180
 
178
- if(JSON.validate(T, value)) { // ... as a Schema
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 provides a set of functions that allow you to compose JSON Schema similar to how you would compose static types with TypeScript. Each function creates a JSON schema fragment which can compose into more complex types. The schemas produced by TypeBox can be passed directly to any JSON Schema compliant validator, or used to reflect runtime metadata for a type.
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 │ properties: {
256
- │ }) │ } │ x: {
257
- │ │ │ type: 'number'
258
- │ │ │ },
259
- │ │ │ y: {
260
- │ │ │ type: 'number'
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 │ type: 'object',
314
- │ x: Type.Number() │ } & { │ properties: {
315
- │ }), │ y: number │ x: {
316
- │ Type.Object({ │ } │ type: 'number'
317
- │ y: Type.Number() │ │ },
318
- }) │ │ y: {
319
- │ ]) │ │ type: 'number'
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 │ properties: {
363
- │ Type.Number() | }> │ x: {
364
- │ ), │ │ type: 'number'
365
- │ y: Type.Optional( │ │ },
366
- │ Type.Number() │ │ y: {
367
- │ ) │ │ type: 'number'
368
- │ }) │ │ }
369
- │ ) │ │ },
370
- │ │ │ required: ['x', 'y']
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
- TypeBox provides a set of extended types that can be used to express schematics for core JavaScript constructs and primitives. Extended types are not valid JSON Schema and will not validate using typical validation. These types however can be used to frame JSON schema and describe callable RPC interfaces that may receive JSON validated data.
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 modifiers that can be applied to an objects properties. This allows for `optional` and `readonly` to be applied to that property. The following table illustates how they map between TypeScript and JSON Schema.
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 additional JSON schema options on the last argument of any given type. The following are some examples.
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
- // string must be an email
525
- const T = Type.String({ format: 'email' })
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
- // number must be a multiple of 2
528
- const T = Type.Number({ multipleOf: 2 })
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
- // array must have at least 5 integer values
531
- const T = Type.Array(Type.Integer(), { minItems: 5 })
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-reference'></a>
681
+ <a name='types-references'></a>
535
682
 
536
- ### Reference
683
+ ### Reference Types
537
684
 
538
- Use `Type.Ref(...)` to create referenced types. The target type must specify an `$id`.
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
- Use `Type.Recursive(...)` to create recursive types.
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] // id is string
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
- Use the conditional module to create [Conditional Types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html). This module implements TypeScript's structural equivalence checks to enable TypeBox types to be conditionally inferred at runtime. This module also provides the [Extract](https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union) and [Exclude](https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers) utility types which are expressed as conditional types in TypeScript.
744
+ Conditional types are supported with `Extends`, `Exclude` and `Extract`. These work the same as in TypeScript.
627
745
 
628
- The conditional module is provided as an optional import.
746
+ #### TypeScript
629
747
 
630
748
  ```typescript
631
- import { Conditional } from '@sinclair/typebox/conditional'
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
- The following table shows the TypeBox mappings between TypeScript and JSON schema.
634
-
756
+ #### TypeBox
635
757
  ```typescript
636
- ┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
637
- TypeBox │ TypeScript │ JSON Schema │
638
- │ │ │ │
639
- ├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
640
- const T = Conditional.Extends( type T = │ const T = { │
641
- │ Type.String(), │ string extends number │ const: false, │
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
- This function can be used to create custom schemas for validators that require specific schema representations. An example of this might be OpenAPI's `nullable` and `enum` schemas which are not provided by TypeBox. The following demonstrates using `Type.Unsafe(...)` to create these types.
780
+ The `Type.Unsafe(...)` type allows specific or non-standard OpenAPI schematics can be constructed.
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
- Use the guard module to test if values are TypeBox types.
815
+ TypeBox provides a `TypeGuard` module used for type value assertions and reflection.
734
816
 
735
817
  ```typescript
736
- import { TypeGuard } from '@sinclair/typebox/guard'
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 provided to enable runtime type reflection on schemas, as well as helping TypeBox internally compose types. 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.
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 includes an optional values module that can be used to perform common operations on JavaScript values. This module enables one to create, check and cast values from types. It also provides functionality to check equality, clone and diff and patch JavaScript values. The value module is provided as an optional import.
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 TypeBox type. TypeBox will use default values if specified.
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) Json Pointers.
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 constructs JSON Schema draft 6 compliant schematics and can be used with any validator that supports this specification. In JavaScript, an ideal validator to use is Ajv which supports draft 6 as well as more recent revisions to the specification. In addition to Ajv, TypeBox provides an optional built in type compiler which can offer faster runtime type compilation, as well as providing high performance data validation for TypeBox types only.
1032
+ TypeBox types targets JSON Schema draft 6 so is immediately 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 these validators.
1034
+ The following details using both 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 with additional string formats.
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 Just-In-Time (JIT) runtime compiler that can be used to convert TypeBox types into fast validation routines. This compiler is specifically tuned for fast compilation and validation for TypeBox types only.
1081
+ The TypeBox TypeCompiler is a high performance JIT compiler that compiles TypeBox types into optimized JavaScript validation routines. The compiler is tuned both for fast compilation and value assertion. It is designed primarily for integrating into application frameworks 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 generate diagnostics for a value. The `Errors(...)` function will run an exhaustive check across the value and yield any error found. For performance, this function should only be called after failed `Check(...)`.
1101
+ Use the `Errors(...)` function to produce diagnostics for a value. The `Errors(...)` function will return an iterator that will perform an exhaustive check across the value and yield any error found. For performance, this function should only be called after failed `Check(...)`.
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 provides an extensible TypeSystem module that enables developers to define additional types above and beyond the built in type set. This module also allows developers to define custom string formats as well as override certain type checking behaviours.
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 `CreateType(...)` function to specify custom type. This function will return a type factory function that can be used to construct the type. The following creates and registers a BigNumber type which will statically infer as `bigint`.
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 BigNumberOptions = { minimum?: bigint; maximum?: bigint }
1163
+ type PointType = { x: number, y: number } // The Static<T> Type
1072
1164
 
1073
- const BigNumber = TypeSystem.CreateType<bigint, BigNumberOptions>(
1074
- 'BigNumber',
1075
- (options, value) => {
1076
- if (typeof value !== 'bigint') return false
1077
- if (options.maximum !== undefined && value > options.maximum) return false
1078
- if (options.minimum !== undefined && value < options.minimum) return false
1079
- return true
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
- const T = BigNumber({ minimum: 10n, maximum: 20n }) // const T = {
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 C = TypeCompiler.Compile(T)
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 `CreateFormat(...)` function to specify user defined string formats. The following creates a custom string format that checks for lowercase.
1184
+ Use the `Format(...)` function to create a custom string formats. 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
- TypeSystem.CreateFormat('lowercase', value => value === value.toLowerCase())
1189
+ const T = Type.String({ format: 'lowercase' })
1115
1190
 
1116
- //--------------------------------------------------------------------------------------------
1117
- //
1118
- // Use the format by creating string types with the 'format' option
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
- const T = Type.String({ format: 'lowercase' })
1207
+ TypeSystem.AllowArrayObjects = true
1123
1208
 
1124
- const A = Value.Check(T, 'action') // const A = true
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
- const B = Value.Check(T, 'ACTION') // const B = false
1213
+ TypeSystem.AllowNaN = true
1127
1214
  ```
1128
1215
 
1129
1216
  <a name='benchmark'></a>