@sinclair/typebox 0.24.32 → 0.24.35
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/package.json +1 -1
- package/readme.md +319 -186
- package/value/cast.d.ts +0 -3
- package/value/cast.js +12 -9
- package/value/clone.d.ts +3 -0
- package/value/clone.js +65 -0
- package/value/delta.d.ts +22 -0
- package/value/delta.js +169 -0
- package/value/equal.d.ts +3 -0
- package/value/equal.js +74 -0
- package/value/is.d.ts +10 -0
- package/value/is.js +49 -0
- package/value/pointer.d.ts +11 -0
- package/value/pointer.js +108 -0
- package/value/value.d.ts +15 -5
- package/value/value.js +29 -6
package/readme.md
CHANGED
|
@@ -56,21 +56,34 @@ License MIT
|
|
|
56
56
|
- [Overview](#overview)
|
|
57
57
|
- [Usage](#usage)
|
|
58
58
|
- [Types](#types)
|
|
59
|
-
- [
|
|
60
|
-
- [
|
|
61
|
-
- [
|
|
62
|
-
- [
|
|
63
|
-
- [
|
|
64
|
-
- [
|
|
65
|
-
- [
|
|
66
|
-
- [Conditional
|
|
59
|
+
- [Standard](#types-standard)
|
|
60
|
+
- [Modifiers](#types-modifiers)
|
|
61
|
+
- [Options](#types-options)
|
|
62
|
+
- [Extended](#types-extended)
|
|
63
|
+
- [Reference](#types-reference)
|
|
64
|
+
- [Recursive](#types-recursive)
|
|
65
|
+
- [Generic](#types-generic)
|
|
66
|
+
- [Conditional](#types-conditional)
|
|
67
|
+
- [Unsafe](#types-unsafe)
|
|
68
|
+
- [Guards](#types-guards)
|
|
69
|
+
- [Strict](#types-strict)
|
|
67
70
|
- [Values](#values)
|
|
68
|
-
- [
|
|
69
|
-
- [
|
|
70
|
-
- [
|
|
71
|
-
- [
|
|
72
|
-
- [
|
|
71
|
+
- [Create](#values-create)
|
|
72
|
+
- [Clone](#values-clone)
|
|
73
|
+
- [Check](#values-check)
|
|
74
|
+
- [Cast](#values-cast)
|
|
75
|
+
- [Equal](#values-equal)
|
|
76
|
+
- [Diff](#values-diff)
|
|
77
|
+
- [Patch](#values-patch)
|
|
78
|
+
- [Errors](#values-errors)
|
|
79
|
+
- [TypeCheck](#typecheck)
|
|
80
|
+
- [Ajv](#typecheck-ajv)
|
|
81
|
+
- [Compiler](#typecheck-compiler)
|
|
82
|
+
- [Formats](#typecheck-formats)
|
|
73
83
|
- [Benchmark](#benchmark)
|
|
84
|
+
- [Compile](#benchmark-compile)
|
|
85
|
+
- [Validate](#benchmark-validate)
|
|
86
|
+
- [Compression](#benchmark-compression)
|
|
74
87
|
- [Contribute](#contribute)
|
|
75
88
|
|
|
76
89
|
<a name="Example"></a>
|
|
@@ -148,9 +161,17 @@ function receive(value: T) { // ... as a Type
|
|
|
148
161
|
}
|
|
149
162
|
```
|
|
150
163
|
|
|
164
|
+
<a name='types'></a>
|
|
165
|
+
|
|
151
166
|
## Types
|
|
152
167
|
|
|
153
|
-
|
|
168
|
+
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.
|
|
169
|
+
|
|
170
|
+
<a name='types-standard'></a>
|
|
171
|
+
|
|
172
|
+
### Standard
|
|
173
|
+
|
|
174
|
+
The following table lists the standard TypeBox types.
|
|
154
175
|
|
|
155
176
|
```typescript
|
|
156
177
|
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
|
|
@@ -342,7 +363,9 @@ The following table outlines the TypeBox mappings between TypeScript and JSON sc
|
|
|
342
363
|
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
343
364
|
```
|
|
344
365
|
|
|
345
|
-
|
|
366
|
+
<a name='types-modifiers'></a>
|
|
367
|
+
|
|
368
|
+
### Modifiers
|
|
346
369
|
|
|
347
370
|
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.
|
|
348
371
|
|
|
@@ -384,7 +407,9 @@ TypeBox provides modifiers that can be applied to an objects properties. This al
|
|
|
384
407
|
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
385
408
|
```
|
|
386
409
|
|
|
387
|
-
|
|
410
|
+
<a name='types-options'></a>
|
|
411
|
+
|
|
412
|
+
### Options
|
|
388
413
|
|
|
389
414
|
You can pass additional JSON schema options on the last argument of any given type. The following are some examples.
|
|
390
415
|
|
|
@@ -399,7 +424,9 @@ const T = Type.Number({ multipleOf: 2 })
|
|
|
399
424
|
const T = Type.Array(Type.Integer(), { minItems: 5 })
|
|
400
425
|
```
|
|
401
426
|
|
|
402
|
-
|
|
427
|
+
<a name='types-extended'></a>
|
|
428
|
+
|
|
429
|
+
### Extended
|
|
403
430
|
|
|
404
431
|
In addition to JSON schema types, TypeBox provides several extended types that allow for `function` and `constructor` types to be composed. These additional types are not valid JSON Schema and will not validate using typical JSON Schema validation. However, these types can be used to frame JSON schema and describe callable interfaces that may receive JSON validated data. These types are as follows.
|
|
405
432
|
|
|
@@ -461,7 +488,9 @@ In addition to JSON schema types, TypeBox provides several extended types that a
|
|
|
461
488
|
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
462
489
|
```
|
|
463
490
|
|
|
464
|
-
|
|
491
|
+
<a name='types-reference'></a>
|
|
492
|
+
|
|
493
|
+
### Reference
|
|
465
494
|
|
|
466
495
|
Use `Type.Ref(...)` to create referenced types. The target type must specify an `$id`.
|
|
467
496
|
|
|
@@ -476,7 +505,9 @@ const R = Type.Ref(T) // const R = {
|
|
|
476
505
|
// }
|
|
477
506
|
```
|
|
478
507
|
|
|
479
|
-
|
|
508
|
+
<a name='types-recursive'></a>
|
|
509
|
+
|
|
510
|
+
### Recursive
|
|
480
511
|
|
|
481
512
|
Use `Type.Recursive(...)` to create recursive types.
|
|
482
513
|
|
|
@@ -513,7 +544,9 @@ function test(node: Node) {
|
|
|
513
544
|
}
|
|
514
545
|
```
|
|
515
546
|
|
|
516
|
-
|
|
547
|
+
<a name='types-generic'></a>
|
|
548
|
+
|
|
549
|
+
### Generic
|
|
517
550
|
|
|
518
551
|
Use functions to create generic types. The following creates a generic `Nullable<T>` type.
|
|
519
552
|
|
|
@@ -543,59 +576,9 @@ const U = Nullable(Type.Number()) // const U = {
|
|
|
543
576
|
type U = Static<typeof U> // type U = number | null
|
|
544
577
|
```
|
|
545
578
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
Use `Type.Unsafe(...)` to create custom schemas with user defined inference rules.
|
|
549
|
-
|
|
550
|
-
```typescript
|
|
551
|
-
const T = Type.Unsafe<string>({ type: 'number' }) // const T = {
|
|
552
|
-
// type: 'number'
|
|
553
|
-
// }
|
|
554
|
-
|
|
555
|
-
type T = Static<typeof T> // type T = string
|
|
556
|
-
```
|
|
557
|
-
|
|
558
|
-
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.
|
|
579
|
+
<a name='types-conditional'></a>
|
|
559
580
|
|
|
560
|
-
|
|
561
|
-
import { Type, Static, TSchema } from '@sinclair/typebox'
|
|
562
|
-
|
|
563
|
-
//--------------------------------------------------------------------------------------------
|
|
564
|
-
//
|
|
565
|
-
// Nullable<T>
|
|
566
|
-
//
|
|
567
|
-
//--------------------------------------------------------------------------------------------
|
|
568
|
-
|
|
569
|
-
function Nullable<T extends TSchema>(schema: T) {
|
|
570
|
-
return Type.Unsafe<Static<T> | null>({ ...schema, nullable: true })
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
const T = Nullable(Type.String()) // const T = {
|
|
574
|
-
// type: 'string',
|
|
575
|
-
// nullable: true
|
|
576
|
-
// }
|
|
577
|
-
|
|
578
|
-
type T = Static<typeof T> // type T = string | null
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
//--------------------------------------------------------------------------------------------
|
|
582
|
-
//
|
|
583
|
-
// StringEnum<string[]>
|
|
584
|
-
//
|
|
585
|
-
//--------------------------------------------------------------------------------------------
|
|
586
|
-
|
|
587
|
-
function StringEnum<T extends string[]>(values: [...T]) {
|
|
588
|
-
return Type.Unsafe<T[number]>({ type: 'string', enum: values })
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
const T = StringEnum(['A', 'B', 'C']) // const T = {
|
|
592
|
-
// enum: ['A', 'B', 'C']
|
|
593
|
-
// }
|
|
594
|
-
|
|
595
|
-
type T = Static<typeof T> // type T = 'A' | 'B' | 'C'
|
|
596
|
-
```
|
|
597
|
-
|
|
598
|
-
## Conditional Types
|
|
581
|
+
### Conditional
|
|
599
582
|
|
|
600
583
|
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.
|
|
601
584
|
|
|
@@ -646,85 +629,63 @@ The following table shows the TypeBox mappings between TypeScript and JSON schem
|
|
|
646
629
|
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
647
630
|
```
|
|
648
631
|
|
|
649
|
-
|
|
632
|
+
<a name='types-unsafe'></a>
|
|
650
633
|
|
|
651
|
-
|
|
634
|
+
### Unsafe
|
|
652
635
|
|
|
653
|
-
|
|
636
|
+
Use `Type.Unsafe(...)` to create custom schemas with user defined inference rules.
|
|
654
637
|
|
|
655
638
|
```typescript
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
```typescript
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
const T = Type.Object({ x: Type.Number(), y: Type.Number() }, { additionalProperties: false })
|
|
663
|
-
|
|
664
|
-
//--------------------------------------------------------------------------------------------
|
|
665
|
-
//
|
|
666
|
-
// Use Value.Create(T) to create a value from T.
|
|
667
|
-
//
|
|
668
|
-
//--------------------------------------------------------------------------------------------
|
|
639
|
+
const T = Type.Unsafe<string>({ type: 'number' }) // const T = {
|
|
640
|
+
// type: 'number'
|
|
641
|
+
// }
|
|
669
642
|
|
|
670
|
-
|
|
643
|
+
type T = Static<typeof T> // type T = string
|
|
644
|
+
```
|
|
671
645
|
|
|
672
|
-
|
|
673
|
-
//
|
|
674
|
-
// Use Value.Check(T, ...) to check if a value is of type T.
|
|
675
|
-
//
|
|
676
|
-
//--------------------------------------------------------------------------------------------
|
|
646
|
+
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.
|
|
677
647
|
|
|
678
|
-
|
|
648
|
+
```typescript
|
|
649
|
+
import { Type, Static, TSchema } from '@sinclair/typebox'
|
|
679
650
|
|
|
680
651
|
//--------------------------------------------------------------------------------------------
|
|
681
652
|
//
|
|
682
|
-
//
|
|
653
|
+
// Nullable<T>
|
|
683
654
|
//
|
|
684
655
|
//--------------------------------------------------------------------------------------------
|
|
685
656
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
const C = Value.Cast(T, { x: 1, y: 2, z: 3 }) // const C = { x: 1, y: 2 }
|
|
691
|
-
```
|
|
692
|
-
|
|
693
|
-
## Formats
|
|
694
|
-
|
|
695
|
-
Use the format module to create user defined string formats. This module enables programmatic validation of strings that cannot be easily validated with [pattern](https://json-schema.org/understanding-json-schema/reference/regular_expressions.html) expressions. The format module is used by the Value and TypeCompiler modules only. If using Ajv, please refer to the official Ajv format documentation located [here](https://ajv.js.org/guide/formats.html).
|
|
696
|
-
|
|
697
|
-
The format module is an optional import.
|
|
698
|
-
|
|
699
|
-
```typescript
|
|
700
|
-
import { Format } from '@sinclair/typebox/format'
|
|
701
|
-
```
|
|
657
|
+
function Nullable<T extends TSchema>(schema: T) {
|
|
658
|
+
return Type.Unsafe<Static<T> | null>({ ...schema, nullable: true })
|
|
659
|
+
}
|
|
702
660
|
|
|
703
|
-
|
|
661
|
+
const T = Nullable(Type.String()) // const T = {
|
|
662
|
+
// type: 'string',
|
|
663
|
+
// nullable: true
|
|
664
|
+
// }
|
|
704
665
|
|
|
705
|
-
|
|
706
|
-
//--------------------------------------------------------------------------------------------
|
|
707
|
-
//
|
|
708
|
-
// Use Format.Set(format, func) to define custom format
|
|
709
|
-
//
|
|
710
|
-
//--------------------------------------------------------------------------------------------
|
|
666
|
+
type T = Static<typeof T> // type T = string | null
|
|
711
667
|
|
|
712
|
-
Format.Set('palindrome', value => value === value.split('').reverse().join(''))
|
|
713
668
|
|
|
714
669
|
//--------------------------------------------------------------------------------------------
|
|
715
670
|
//
|
|
716
|
-
//
|
|
671
|
+
// StringEnum<string[]>
|
|
717
672
|
//
|
|
718
673
|
//--------------------------------------------------------------------------------------------
|
|
719
674
|
|
|
720
|
-
|
|
675
|
+
function StringEnum<T extends string[]>(values: [...T]) {
|
|
676
|
+
return Type.Unsafe<T[number]>({ type: 'string', enum: values })
|
|
677
|
+
}
|
|
721
678
|
|
|
722
|
-
|
|
679
|
+
const T = StringEnum(['A', 'B', 'C']) // const T = {
|
|
680
|
+
// enum: ['A', 'B', 'C']
|
|
681
|
+
// }
|
|
723
682
|
|
|
724
|
-
|
|
683
|
+
type T = Static<typeof T> // type T = 'A' | 'B' | 'C'
|
|
725
684
|
```
|
|
726
685
|
|
|
727
|
-
|
|
686
|
+
<a name='types-guards'></a>
|
|
687
|
+
|
|
688
|
+
### Guards
|
|
728
689
|
|
|
729
690
|
Use the guard module to test if values are TypeBox types.
|
|
730
691
|
|
|
@@ -739,7 +700,9 @@ if(TypeGuard.TString(T)) {
|
|
|
739
700
|
}
|
|
740
701
|
```
|
|
741
702
|
|
|
742
|
-
|
|
703
|
+
<a name='types-strict'></a>
|
|
704
|
+
|
|
705
|
+
### Strict
|
|
743
706
|
|
|
744
707
|
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.
|
|
745
708
|
|
|
@@ -766,21 +729,153 @@ const U = Type.Strict(T) // const U = {
|
|
|
766
729
|
// }
|
|
767
730
|
```
|
|
768
731
|
|
|
769
|
-
|
|
732
|
+
<a name='values'></a>
|
|
733
|
+
|
|
734
|
+
## Values
|
|
735
|
+
|
|
736
|
+
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.
|
|
737
|
+
|
|
738
|
+
```typescript
|
|
739
|
+
import { Value } from '@sinclair/typebox/value'
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
<a name='values-create'></a>
|
|
743
|
+
|
|
744
|
+
### Create
|
|
745
|
+
|
|
746
|
+
Use the Create function to create a value from a TypeBox type. TypeBox will use default values if specified.
|
|
747
|
+
|
|
748
|
+
```typescript
|
|
749
|
+
const T = Type.Object({ x: Type.Number(), y: Type.Number({ default: 42 }) })
|
|
750
|
+
|
|
751
|
+
const A = Value.Create(T) // const A = { x: 0, y: 42 }
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
<a name='values-clone'></a>
|
|
755
|
+
|
|
756
|
+
### Clone
|
|
757
|
+
|
|
758
|
+
Use the Clone function to deeply clone a value
|
|
759
|
+
|
|
760
|
+
```typescript
|
|
761
|
+
const A = Value.Clone({ x: 1, y: 2, z: 3 }) // const A = { x: 1, y: 2, z: 3 }
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
<a name='values-check'></a>
|
|
765
|
+
|
|
766
|
+
### Check
|
|
767
|
+
|
|
768
|
+
Use the Check function to type check a value
|
|
769
|
+
|
|
770
|
+
```typescript
|
|
771
|
+
const T = Type.Object({ x: Type.Number() })
|
|
772
|
+
|
|
773
|
+
const R = Value.Check(T, { x: 1 }) // const R = true
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
<a name='values-cast'></a>
|
|
777
|
+
|
|
778
|
+
### Cast
|
|
779
|
+
|
|
780
|
+
Use the Cast function to cast a value into a type. The cast function will retain as much information as possible from the original value.
|
|
781
|
+
|
|
782
|
+
```typescript
|
|
783
|
+
const T = Type.Object({ x: Type.Number(), y: Type.Number() }, { additionalProperties: false })
|
|
784
|
+
|
|
785
|
+
const X = Value.Cast(T, null) // const X = { x: 0, y: 0 }
|
|
786
|
+
|
|
787
|
+
const Y = Value.Cast(T, { x: 1 }) // const Y = { x: 1, y: 0 }
|
|
788
|
+
|
|
789
|
+
const Z = Value.Cast(T, { x: 1, y: 2, z: 3 }) // const Z = { x: 1, y: 2 }
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
<a name='values-equal'></a>
|
|
793
|
+
|
|
794
|
+
### Equal
|
|
795
|
+
|
|
796
|
+
Use the Equal function to deeply check for value equality.
|
|
797
|
+
|
|
798
|
+
```typescript
|
|
799
|
+
const R = Value.Equal( // const R = true
|
|
800
|
+
{ x: 1, y: 2, z: 3 },
|
|
801
|
+
{ x: 1, y: 2, z: 3 }
|
|
802
|
+
)
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
<a name='values-diff'></a>
|
|
806
|
+
|
|
807
|
+
### Diff
|
|
808
|
+
|
|
809
|
+
Use the Diff function to produce a sequence of edits to transform one value into another.
|
|
810
|
+
|
|
811
|
+
```typescript
|
|
812
|
+
const E = Value.Diff<any>( // const E = [
|
|
813
|
+
{ x: 1, y: 2, z: 3 }, // { type: 'update', path: '/y', value: 4 },
|
|
814
|
+
{ y: 4, z: 5, w: 6 } // { type: 'update', path: '/z', value: 5 },
|
|
815
|
+
) // { type: 'insert', path: '/w', value: 6 },
|
|
816
|
+
// { type: 'delete', path: '/x' }
|
|
817
|
+
// ]
|
|
818
|
+
```
|
|
819
|
+
|
|
820
|
+
<a name='values-patch'></a>
|
|
821
|
+
|
|
822
|
+
### Patch
|
|
823
|
+
|
|
824
|
+
Use the Patch function to apply edits
|
|
825
|
+
|
|
826
|
+
```typescript
|
|
827
|
+
const A = { x: 1, y: 2 }
|
|
828
|
+
|
|
829
|
+
const B = { x: 3 }
|
|
830
|
+
|
|
831
|
+
const E = Value.Diff<any>(A, B) // const E = [
|
|
832
|
+
// { type: 'update', path: '/x', value: 3 },
|
|
833
|
+
// { type: 'delete', path: '/y' }
|
|
834
|
+
// ]
|
|
835
|
+
|
|
836
|
+
const C = Value.Patch<any>(A, E) // const C = { x: 3 }
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
<a name='values-errors'></a>
|
|
841
|
+
|
|
842
|
+
### Errors
|
|
770
843
|
|
|
771
|
-
|
|
844
|
+
Use the Errors function enumerate validation errors.
|
|
845
|
+
|
|
846
|
+
```typescript
|
|
847
|
+
const T = Type.Object({ x: Type.Number(), y: Type.Number() })
|
|
848
|
+
|
|
849
|
+
const R = [...Value.Errors(T, { x: '42' })] // const R = [{
|
|
850
|
+
// schema: { type: 'number' },
|
|
851
|
+
// path: '/x',
|
|
852
|
+
// value: '42',
|
|
853
|
+
// message: 'Expected number'
|
|
854
|
+
// }, {
|
|
855
|
+
// schema: { type: 'number' },
|
|
856
|
+
// path: '/y',
|
|
857
|
+
// value: undefined,
|
|
858
|
+
// message: 'Expected number'
|
|
859
|
+
// }]
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
<a name='typecheck'></a>
|
|
863
|
+
|
|
864
|
+
## TypeCheck
|
|
865
|
+
|
|
866
|
+
TypeBox is written to target JSON Schema Draft 6 and can be used with any Draft 6 compliant validator. TypeBox is developed and tested against Ajv and can be used in any application already making use of this validator. Additionally, TypeBox also provides an optional type compiler that can be used to attain improved compilation and validation performance for certain application types.
|
|
867
|
+
|
|
868
|
+
<a name='typecheck-ajv'></a>
|
|
869
|
+
|
|
870
|
+
### Ajv
|
|
871
|
+
|
|
872
|
+
The following example shows setting up Ajv to work with TypeBox.
|
|
772
873
|
|
|
773
874
|
```bash
|
|
774
875
|
$ npm install ajv ajv-formats --save
|
|
775
876
|
```
|
|
776
877
|
|
|
777
878
|
```typescript
|
|
778
|
-
//--------------------------------------------------------------------------------------------
|
|
779
|
-
//
|
|
780
|
-
// Import TypeBox and Ajv
|
|
781
|
-
//
|
|
782
|
-
//--------------------------------------------------------------------------------------------
|
|
783
|
-
|
|
784
879
|
import { Type } from '@sinclair/typebox'
|
|
785
880
|
import addFormats from 'ajv-formats'
|
|
786
881
|
import Ajv from 'ajv'
|
|
@@ -829,9 +924,9 @@ const T = Type.Object({
|
|
|
829
924
|
const R = ajv.validate(T, { x: 1, y: 2, z: 3 }) // const R = true
|
|
830
925
|
```
|
|
831
926
|
|
|
832
|
-
|
|
927
|
+
<a name='typecheck-compiler'></a>
|
|
833
928
|
|
|
834
|
-
|
|
929
|
+
### Compiler
|
|
835
930
|
|
|
836
931
|
TypeBox provides an optional high performance just-in-time (JIT) compiler and type checker that can be used in applications that require extremely fast validation. Note that this compiler is optimized for TypeBox types only where the schematics are known in advance. If defining custom types with `Type.Unsafe<T>` please consider Ajv.
|
|
837
932
|
|
|
@@ -894,12 +989,44 @@ console.log(C.Code()) // return function check(va
|
|
|
894
989
|
// }
|
|
895
990
|
```
|
|
896
991
|
|
|
992
|
+
<a name='typecheck-formats'></a>
|
|
993
|
+
|
|
994
|
+
### Formats
|
|
995
|
+
|
|
996
|
+
Use the format module to create user defined string formats. The format module is used by the Value and TypeCompiler modules only. If using Ajv, please refer to the official Ajv format documentation located [here](https://ajv.js.org/guide/formats.html).
|
|
997
|
+
|
|
998
|
+
The format module is an optional import.
|
|
999
|
+
|
|
1000
|
+
```typescript
|
|
1001
|
+
import { Format } from '@sinclair/typebox/format'
|
|
1002
|
+
```
|
|
1003
|
+
|
|
1004
|
+
The following creates a `palindrome` string format.
|
|
1005
|
+
|
|
1006
|
+
```typescript
|
|
1007
|
+
Format.Set('palindrome', value => value === value.split('').reverse().join(''))
|
|
1008
|
+
```
|
|
1009
|
+
|
|
1010
|
+
Once set, this format can then be used by the TypeCompiler and Value modules.
|
|
1011
|
+
|
|
1012
|
+
```typescript
|
|
1013
|
+
const T = Type.String({ format: 'palindrome' })
|
|
1014
|
+
|
|
1015
|
+
const A = TypeCompiler.Compile(T).Check('engine') // const A = false
|
|
1016
|
+
|
|
1017
|
+
const B = Value.Check(T, 'kayak') // const B = true
|
|
1018
|
+
```
|
|
1019
|
+
|
|
1020
|
+
<a name='benchmark'></a>
|
|
1021
|
+
|
|
897
1022
|
## Benchmark
|
|
898
1023
|
|
|
899
1024
|
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.11.0.
|
|
900
1025
|
|
|
901
1026
|
For additional comparative benchmarks, please refer to [typescript-runtime-type-benchmarks](https://moltar.github.io/typescript-runtime-type-benchmarks/).
|
|
902
1027
|
|
|
1028
|
+
<a name='benchmark-compile'></a>
|
|
1029
|
+
|
|
903
1030
|
### Compile
|
|
904
1031
|
|
|
905
1032
|
This benchmark measures compilation performance for varying types. You can review this benchmark [here](https://github.com/sinclairzx81/typebox/blob/master/benchmark/measurement/module/compile.ts).
|
|
@@ -908,32 +1035,34 @@ This benchmark measures compilation performance for varying types. You can revie
|
|
|
908
1035
|
┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┐
|
|
909
1036
|
│ (index) │ Iterations │ Ajv │ TypeCompiler │ Performance │
|
|
910
1037
|
├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┤
|
|
911
|
-
│ Number │ 2000 │ '
|
|
912
|
-
│ String │ 2000 │ '
|
|
913
|
-
│ Boolean │ 2000 │ '
|
|
914
|
-
│ Null │ 2000 │ '
|
|
915
|
-
│ RegEx │ 2000 │ '
|
|
916
|
-
│ ObjectA │ 2000 │ '
|
|
917
|
-
│ ObjectB │ 2000 │ '
|
|
918
|
-
│ Tuple │ 2000 │ '
|
|
919
|
-
│ Union │ 2000 │ '
|
|
920
|
-
│ Vector4 │ 2000 │ '
|
|
921
|
-
│ Matrix4 │ 2000 │ '
|
|
922
|
-
│ Literal_String │ 2000 │ '
|
|
923
|
-
│ Literal_Number │ 2000 │ '
|
|
924
|
-
│ Literal_Boolean │ 2000 │ '
|
|
925
|
-
│ Array_Number │ 2000 │ '
|
|
926
|
-
│ Array_String │ 2000 │ '
|
|
927
|
-
│ Array_Boolean │ 2000 │ '
|
|
928
|
-
│ Array_ObjectA │ 2000 │ '
|
|
929
|
-
│ Array_ObjectB │ 2000 │ '
|
|
930
|
-
│ Array_Tuple │ 2000 │ '
|
|
931
|
-
│ Array_Union │ 2000 │ '
|
|
932
|
-
│ Array_Vector4 │ 2000 │ '
|
|
933
|
-
│ Array_Matrix4 │ 2000 │ '
|
|
1038
|
+
│ Number │ 2000 │ ' 410 ms' │ ' 10 ms' │ ' 41.00 x' │
|
|
1039
|
+
│ String │ 2000 │ ' 321 ms' │ ' 8 ms' │ ' 40.13 x' │
|
|
1040
|
+
│ Boolean │ 2000 │ ' 314 ms' │ ' 6 ms' │ ' 52.33 x' │
|
|
1041
|
+
│ Null │ 2000 │ ' 273 ms' │ ' 6 ms' │ ' 45.50 x' │
|
|
1042
|
+
│ RegEx │ 2000 │ ' 485 ms' │ ' 11 ms' │ ' 44.09 x' │
|
|
1043
|
+
│ ObjectA │ 2000 │ ' 2867 ms' │ ' 41 ms' │ ' 69.93 x' │
|
|
1044
|
+
│ ObjectB │ 2000 │ ' 3018 ms' │ ' 30 ms' │ ' 100.60 x' │
|
|
1045
|
+
│ Tuple │ 2000 │ ' 1298 ms' │ ' 21 ms' │ ' 61.81 x' │
|
|
1046
|
+
│ Union │ 2000 │ ' 1340 ms' │ ' 23 ms' │ ' 58.26 x' │
|
|
1047
|
+
│ Vector4 │ 2000 │ ' 1794 ms' │ ' 22 ms' │ ' 81.55 x' │
|
|
1048
|
+
│ Matrix4 │ 2000 │ ' 1037 ms' │ ' 12 ms' │ ' 86.42 x' │
|
|
1049
|
+
│ Literal_String │ 2000 │ ' 380 ms' │ ' 9 ms' │ ' 42.22 x' │
|
|
1050
|
+
│ Literal_Number │ 2000 │ ' 446 ms' │ ' 8 ms' │ ' 55.75 x' │
|
|
1051
|
+
│ Literal_Boolean │ 2000 │ ' 400 ms' │ ' 4 ms' │ ' 100.00 x' │
|
|
1052
|
+
│ Array_Number │ 2000 │ ' 764 ms' │ ' 6 ms' │ ' 127.33 x' │
|
|
1053
|
+
│ Array_String │ 2000 │ ' 785 ms' │ ' 9 ms' │ ' 87.22 x' │
|
|
1054
|
+
│ Array_Boolean │ 2000 │ ' 796 ms' │ ' 6 ms' │ ' 132.67 x' │
|
|
1055
|
+
│ Array_ObjectA │ 2000 │ ' 3678 ms' │ ' 34 ms' │ ' 108.18 x' │
|
|
1056
|
+
│ Array_ObjectB │ 2000 │ ' 3875 ms' │ ' 34 ms' │ ' 113.97 x' │
|
|
1057
|
+
│ Array_Tuple │ 2000 │ ' 2231 ms' │ ' 15 ms' │ ' 148.73 x' │
|
|
1058
|
+
│ Array_Union │ 2000 │ ' 1713 ms' │ ' 18 ms' │ ' 95.17 x' │
|
|
1059
|
+
│ Array_Vector4 │ 2000 │ ' 2381 ms' │ ' 16 ms' │ ' 148.81 x' │
|
|
1060
|
+
│ Array_Matrix4 │ 2000 │ ' 1644 ms' │ ' 14 ms' │ ' 117.43 x' │
|
|
934
1061
|
└──────────────────┴────────────┴──────────────┴──────────────┴──────────────┘
|
|
935
1062
|
```
|
|
936
1063
|
|
|
1064
|
+
<a name='benchmark-validate'></a>
|
|
1065
|
+
|
|
937
1066
|
### Validate
|
|
938
1067
|
|
|
939
1068
|
This benchmark measures validation performance for varying types. You can review this benchmark [here](https://github.com/sinclairzx81/typebox/blob/master/benchmark/measurement/module/check.ts).
|
|
@@ -942,34 +1071,36 @@ This benchmark measures validation performance for varying types. You can review
|
|
|
942
1071
|
┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
|
|
943
1072
|
│ (index) │ Iterations │ ValueCheck │ Ajv │ TypeCompiler │ Performance │
|
|
944
1073
|
├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┼──────────────┤
|
|
945
|
-
│ Number │ 1000000 │ '
|
|
946
|
-
│ String │ 1000000 │ '
|
|
947
|
-
│ Boolean │ 1000000 │ '
|
|
948
|
-
│ Null │ 1000000 │ ' 29 ms' │ '
|
|
949
|
-
│ RegEx │ 1000000 │ '
|
|
950
|
-
│ ObjectA │ 1000000 │ '
|
|
951
|
-
│ ObjectB │ 1000000 │ ' 995 ms' │ '
|
|
952
|
-
│ Tuple │ 1000000 │ '
|
|
953
|
-
│ Union │ 1000000 │ '
|
|
954
|
-
│ Recursive │ 1000000 │ '
|
|
955
|
-
│ Vector4 │ 1000000 │ '
|
|
956
|
-
│ Matrix4 │ 1000000 │ '
|
|
957
|
-
│ Literal_String │ 1000000 │ ' 46 ms' │ ' 21 ms' │ '
|
|
958
|
-
│ Literal_Number │ 1000000 │ '
|
|
959
|
-
│ Literal_Boolean │ 1000000 │ '
|
|
960
|
-
│ Array_Number │ 1000000 │ '
|
|
961
|
-
│ Array_String │ 1000000 │ '
|
|
962
|
-
│ Array_Boolean │ 1000000 │ '
|
|
963
|
-
│ Array_ObjectA │ 1000000 │ '
|
|
964
|
-
│ Array_ObjectB │ 1000000 │ '
|
|
965
|
-
│ Array_Tuple │ 1000000 │ '
|
|
966
|
-
│ Array_Union │ 1000000 │ '
|
|
967
|
-
│ Array_Recursive │ 1000000 │ '
|
|
968
|
-
│ Array_Vector4 │ 1000000 │ '
|
|
969
|
-
│ Array_Matrix4 │ 1000000 │ '
|
|
1074
|
+
│ Number │ 1000000 │ ' 29 ms' │ ' 6 ms' │ ' 5 ms' │ ' 1.20 x' │
|
|
1075
|
+
│ String │ 1000000 │ ' 24 ms' │ ' 23 ms' │ ' 11 ms' │ ' 2.09 x' │
|
|
1076
|
+
│ Boolean │ 1000000 │ ' 21 ms' │ ' 22 ms' │ ' 10 ms' │ ' 2.20 x' │
|
|
1077
|
+
│ Null │ 1000000 │ ' 29 ms' │ ' 26 ms' │ ' 15 ms' │ ' 1.73 x' │
|
|
1078
|
+
│ RegEx │ 1000000 │ ' 180 ms' │ ' 46 ms' │ ' 36 ms' │ ' 1.28 x' │
|
|
1079
|
+
│ ObjectA │ 1000000 │ ' 548 ms' │ ' 36 ms' │ ' 24 ms' │ ' 1.50 x' │
|
|
1080
|
+
│ ObjectB │ 1000000 │ ' 995 ms' │ ' 52 ms' │ ' 40 ms' │ ' 1.30 x' │
|
|
1081
|
+
│ Tuple │ 1000000 │ ' 119 ms' │ ' 23 ms' │ ' 14 ms' │ ' 1.64 x' │
|
|
1082
|
+
│ Union │ 1000000 │ ' 308 ms' │ ' 25 ms' │ ' 15 ms' │ ' 1.67 x' │
|
|
1083
|
+
│ Recursive │ 1000000 │ ' 3405 ms' │ ' 458 ms' │ ' 214 ms' │ ' 2.14 x' │
|
|
1084
|
+
│ Vector4 │ 1000000 │ ' 144 ms' │ ' 23 ms' │ ' 12 ms' │ ' 1.92 x' │
|
|
1085
|
+
│ Matrix4 │ 1000000 │ ' 608 ms' │ ' 42 ms' │ ' 29 ms' │ ' 1.45 x' │
|
|
1086
|
+
│ Literal_String │ 1000000 │ ' 46 ms' │ ' 21 ms' │ ' 10 ms' │ ' 2.10 x' │
|
|
1087
|
+
│ Literal_Number │ 1000000 │ ' 48 ms' │ ' 20 ms' │ ' 9 ms' │ ' 2.22 x' │
|
|
1088
|
+
│ Literal_Boolean │ 1000000 │ ' 50 ms' │ ' 20 ms' │ ' 10 ms' │ ' 2.00 x' │
|
|
1089
|
+
│ Array_Number │ 1000000 │ ' 467 ms' │ ' 34 ms' │ ' 19 ms' │ ' 1.79 x' │
|
|
1090
|
+
│ Array_String │ 1000000 │ ' 488 ms' │ ' 32 ms' │ ' 20 ms' │ ' 1.60 x' │
|
|
1091
|
+
│ Array_Boolean │ 1000000 │ ' 476 ms' │ ' 34 ms' │ ' 24 ms' │ ' 1.42 x' │
|
|
1092
|
+
│ Array_ObjectA │ 1000000 │ ' 14220 ms' │ ' 2819 ms' │ ' 1810 ms' │ ' 1.56 x' │
|
|
1093
|
+
│ Array_ObjectB │ 1000000 │ ' 16344 ms' │ ' 3067 ms' │ ' 2147 ms' │ ' 1.43 x' │
|
|
1094
|
+
│ Array_Tuple │ 1000000 │ ' 1702 ms' │ ' 92 ms' │ ' 71 ms' │ ' 1.30 x' │
|
|
1095
|
+
│ Array_Union │ 1000000 │ ' 4754 ms' │ ' 249 ms' │ ' 89 ms' │ ' 2.80 x' │
|
|
1096
|
+
│ Array_Recursive │ 1000000 │ ' 56465 ms' │ ' 6921 ms' │ ' 2411 ms' │ ' 2.87 x' │
|
|
1097
|
+
│ Array_Vector4 │ 1000000 │ ' 1974 ms' │ ' 109 ms' │ ' 55 ms' │ ' 1.98 x' │
|
|
1098
|
+
│ Array_Matrix4 │ 1000000 │ ' 10722 ms' │ ' 400 ms' │ ' 320 ms' │ ' 1.25 x' │
|
|
970
1099
|
└──────────────────┴────────────┴──────────────┴──────────────┴──────────────┴──────────────┘
|
|
971
1100
|
```
|
|
972
1101
|
|
|
1102
|
+
<a name='benchmark-compression'></a>
|
|
1103
|
+
|
|
973
1104
|
### Compression
|
|
974
1105
|
|
|
975
1106
|
The following table lists esbuild compiled and minified sizes for each TypeBox module.
|
|
@@ -980,13 +1111,15 @@ The following table lists esbuild compiled and minified sizes for each TypeBox m
|
|
|
980
1111
|
├──────────────────────┼────────────┼────────────┼─────────────┤
|
|
981
1112
|
│ typebox/compiler │ ' 48 kb' │ ' 24 kb' │ '2.00 x' │
|
|
982
1113
|
│ typebox/conditional │ ' 41 kb' │ ' 16 kb' │ '2.47 x' │
|
|
983
|
-
│ typebox/format │ ' 0 kb' │ ' 0 kb' │ '2.
|
|
1114
|
+
│ typebox/format │ ' 0 kb' │ ' 0 kb' │ '2.66 x' │
|
|
984
1115
|
│ typebox/guard │ ' 20 kb' │ ' 9 kb' │ '2.08 x' │
|
|
985
|
-
│ typebox/value │ '
|
|
1116
|
+
│ typebox/value │ ' 68 kb' │ ' 31 kb' │ '2.15 x' │
|
|
986
1117
|
│ typebox │ ' 11 kb' │ ' 5 kb' │ '1.91 x' │
|
|
987
1118
|
└──────────────────────┴────────────┴────────────┴─────────────┘
|
|
988
1119
|
```
|
|
989
1120
|
|
|
1121
|
+
<a name='contribute'></a>
|
|
1122
|
+
|
|
990
1123
|
## Contribute
|
|
991
1124
|
|
|
992
1125
|
TypeBox is open to community contribution. Please ensure you submit an open issue before submitting your pull request. The TypeBox project preferences open community discussion prior to accepting new features.
|