@sinclair/typebox 0.24.16 → 0.24.19
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 +1 -1
- package/compiler/compiler.js +1 -5
- package/conditional/conditional.d.ts +1 -1
- package/conditional/conditional.js +1 -1
- package/conditional/structural.js +5 -2
- package/package.json +1 -2
- package/readme.md +110 -105
- package/typebox.d.ts +24 -16
- package/typebox.js +37 -16
package/compiler/compiler.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export declare class TypeCheck<T extends Types.TSchema> {
|
|
|
14
14
|
/** Returns true if the value matches the given type. */
|
|
15
15
|
Check(value: unknown): value is Types.Static<T>;
|
|
16
16
|
}
|
|
17
|
-
/** Compiles
|
|
17
|
+
/** Compiles Types for Runtime Type Checking */
|
|
18
18
|
export declare namespace TypeCompiler {
|
|
19
19
|
/** Compiles the given type for runtime type checking. This compiler only accepts known TypeBox types non-inclusive of unsafe types. */
|
|
20
20
|
function Compile<T extends Types.TSchema>(schema: T, references?: Types.TSchema[]): TypeCheck<T>;
|
package/compiler/compiler.js
CHANGED
|
@@ -34,10 +34,6 @@ const Types = require("../typebox");
|
|
|
34
34
|
// TypeCheck
|
|
35
35
|
// -------------------------------------------------------------------
|
|
36
36
|
class TypeCheck {
|
|
37
|
-
schema;
|
|
38
|
-
references;
|
|
39
|
-
checkFunc;
|
|
40
|
-
code;
|
|
41
37
|
constructor(schema, references, checkFunc, code) {
|
|
42
38
|
this.schema = schema;
|
|
43
39
|
this.references = references;
|
|
@@ -61,7 +57,7 @@ exports.TypeCheck = TypeCheck;
|
|
|
61
57
|
// -------------------------------------------------------------------
|
|
62
58
|
// TypeCompiler
|
|
63
59
|
// -------------------------------------------------------------------
|
|
64
|
-
/** Compiles
|
|
60
|
+
/** Compiles Types for Runtime Type Checking */
|
|
65
61
|
var TypeCompiler;
|
|
66
62
|
(function (TypeCompiler) {
|
|
67
63
|
// -------------------------------------------------------------------
|
|
@@ -6,7 +6,7 @@ export interface TExclude<T extends Types.TUnion, U extends Types.TUnion> extend
|
|
|
6
6
|
export interface TExtract<T extends Types.TSchema, U extends Types.TUnion> extends Types.TUnion<any[]> {
|
|
7
7
|
static: Extract<Types.Static<T, this['params']>, Types.Static<U, this['params']>>;
|
|
8
8
|
}
|
|
9
|
-
/**
|
|
9
|
+
/** Conditional Types */
|
|
10
10
|
export declare namespace Conditional {
|
|
11
11
|
/** (Experimental) Creates a conditional expression type */
|
|
12
12
|
function Extends<L extends Types.TSchema, R extends Types.TSchema, T extends Types.TSchema, U extends Types.TSchema>(left: L, right: R, ok: T, fail: U): TExtends<L, R, T, U>;
|
|
@@ -31,7 +31,7 @@ exports.Conditional = void 0;
|
|
|
31
31
|
const Types = require("../typebox");
|
|
32
32
|
const structural_1 = require("./structural");
|
|
33
33
|
const guard_1 = require("../guard");
|
|
34
|
-
/**
|
|
34
|
+
/** Conditional Types */
|
|
35
35
|
var Conditional;
|
|
36
36
|
(function (Conditional) {
|
|
37
37
|
/** (Experimental) Creates a conditional expression type */
|
|
@@ -183,6 +183,9 @@ var Structural;
|
|
|
183
183
|
if (AnyOrUnknownRule(right)) {
|
|
184
184
|
return StructuralResult.True;
|
|
185
185
|
}
|
|
186
|
+
else if (guard_1.TypeGuard.TObject(right) && globalThis.Object.keys(right.properties).length === 0) {
|
|
187
|
+
return StructuralResult.True;
|
|
188
|
+
}
|
|
186
189
|
else if (!guard_1.TypeGuard.TConstructor(right)) {
|
|
187
190
|
return StructuralResult.False;
|
|
188
191
|
}
|
|
@@ -376,8 +379,8 @@ var Structural;
|
|
|
376
379
|
return StructuralResult.True;
|
|
377
380
|
}
|
|
378
381
|
else if (guard_1.TypeGuard.TObject(right)) {
|
|
379
|
-
if (
|
|
380
|
-
return
|
|
382
|
+
if (RecordPattern(left) === '^.*$' && right[Types.Hint] === 'Record') {
|
|
383
|
+
return StructuralResult.True;
|
|
381
384
|
}
|
|
382
385
|
else if (RecordPattern(left) === '^.*$') {
|
|
383
386
|
return StructuralResult.False;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sinclair/typebox",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.19",
|
|
4
4
|
"description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"json-schema",
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
"chai": "^4.3.5",
|
|
36
36
|
"mocha": "^9.2.0",
|
|
37
37
|
"prettier": "^2.7.1",
|
|
38
|
-
"tsd": "^0.19.1",
|
|
39
38
|
"typescript": "^4.7.4"
|
|
40
39
|
}
|
|
41
40
|
}
|
package/readme.md
CHANGED
|
@@ -45,9 +45,9 @@ type T = Static<typeof T> // type T = string
|
|
|
45
45
|
|
|
46
46
|
## Overview
|
|
47
47
|
|
|
48
|
-
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
|
|
48
|
+
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 unified types that can be statically checked by TypeScript and runtime asserted using standard JSON Schema validation.
|
|
49
49
|
|
|
50
|
-
TypeBox can be used as a simple tool to build up complex schemas or integrated into RPC or REST services to help validate
|
|
50
|
+
TypeBox can be used as a simple tool to build up complex schemas or integrated into RPC or REST services to help validate data received over the wire. It offers a type system aligned to the capabilities of TypeScript and can be used equally well in JavaScript environments.
|
|
51
51
|
|
|
52
52
|
License MIT
|
|
53
53
|
|
|
@@ -69,6 +69,7 @@ License MIT
|
|
|
69
69
|
- [Strict](#Strict)
|
|
70
70
|
- [Validation](#Validation)
|
|
71
71
|
- [Compiler](#Compiler)
|
|
72
|
+
- [Benchmark](#Benchmark)
|
|
72
73
|
- [Contribute](#Contribute)
|
|
73
74
|
|
|
74
75
|
<a name="Example"></a>
|
|
@@ -140,7 +141,8 @@ type T = Static<typeof T> // type T = {
|
|
|
140
141
|
function receive(value: T) { // ... as a Type
|
|
141
142
|
|
|
142
143
|
if(JSON.validate(T, value)) { // ... as a Schema
|
|
143
|
-
|
|
144
|
+
|
|
145
|
+
// ok...
|
|
144
146
|
}
|
|
145
147
|
}
|
|
146
148
|
```
|
|
@@ -230,7 +232,7 @@ The following table outlines the TypeBox mappings between TypeScript and JSON sc
|
|
|
230
232
|
│ │ │ }], │
|
|
231
233
|
│ │ │ additionalItems: false, │
|
|
232
234
|
│ │ │ minItems: 2, │
|
|
233
|
-
│ │ │ maxItems: 2
|
|
235
|
+
│ │ │ maxItems: 2 │
|
|
234
236
|
│ │ │ } │
|
|
235
237
|
│ │ │ │
|
|
236
238
|
│ │ │ │
|
|
@@ -252,7 +254,7 @@ The following table outlines the TypeBox mappings between TypeScript and JSON sc
|
|
|
252
254
|
│ y: Type.Number() │ } │ const: 'x' │
|
|
253
255
|
│ }) │ │ }, { │
|
|
254
256
|
│ ) │ │ type: 'string', │
|
|
255
|
-
│ │ │ const: 'y'
|
|
257
|
+
│ │ │ const: 'y' │
|
|
256
258
|
│ │ │ }] │
|
|
257
259
|
│ │ │ } │
|
|
258
260
|
│ │ │ │
|
|
@@ -320,7 +322,7 @@ The following table outlines the TypeBox mappings between TypeScript and JSON sc
|
|
|
320
322
|
│ const T = Type.Pick( │ type T = Pick<{ │ const T = { │
|
|
321
323
|
│ Type.Object({ │ x: number, │ type: 'object', │
|
|
322
324
|
│ x: Type.Number(), │ y: number │ properties: { │
|
|
323
|
-
│ y: Type.Number()
|
|
325
|
+
│ y: Type.Number() | }, 'x'> │ x: { │
|
|
324
326
|
│ }), ['x'] │ │ type: 'number' │
|
|
325
327
|
│ ) │ │ } │
|
|
326
328
|
│ │ │ }, │
|
|
@@ -331,7 +333,7 @@ The following table outlines the TypeBox mappings between TypeScript and JSON sc
|
|
|
331
333
|
│ const T = Type.Omit( │ type T = Omit<{ │ const T = { │
|
|
332
334
|
│ Type.Object({ │ x: number, │ type: 'object', │
|
|
333
335
|
│ x: Type.Number(), │ y: number │ properties: { │
|
|
334
|
-
│ y: Type.Number()
|
|
336
|
+
│ y: Type.Number() | }, 'x'> │ y: { │
|
|
335
337
|
│ }), ['x'] │ │ type: 'number' │
|
|
336
338
|
│ ) │ │ } │
|
|
337
339
|
│ │ │ }, │
|
|
@@ -352,8 +354,8 @@ TypeBox provides modifiers that can be applied to an objects properties. This al
|
|
|
352
354
|
│ │ │ │
|
|
353
355
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
354
356
|
│ const T = Type.Object({ │ type T = { │ const T = { │
|
|
355
|
-
│ name: Type.Optional( │ name?: string
|
|
356
|
-
│ Type.String()
|
|
357
|
+
│ name: Type.Optional( │ name?: string │ type: 'object', │
|
|
358
|
+
│ Type.String() │ } │ properties: { │
|
|
357
359
|
│ ) │ │ name: { │
|
|
358
360
|
│ }) │ │ type: 'string' │
|
|
359
361
|
│ │ │ } │
|
|
@@ -362,8 +364,8 @@ TypeBox provides modifiers that can be applied to an objects properties. This al
|
|
|
362
364
|
│ │ │ │
|
|
363
365
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
364
366
|
│ const T = Type.Object({ │ type T = { │ const T = { │
|
|
365
|
-
│ name: Type.Readonly( │ readonly name: string
|
|
366
|
-
│ Type.String()
|
|
367
|
+
│ name: Type.Readonly( │ readonly name: string │ type: 'object', │
|
|
368
|
+
│ Type.String() │ } │ properties: { │
|
|
367
369
|
│ ) │ │ name: { │
|
|
368
370
|
│ }) │ │ type: 'string' │
|
|
369
371
|
│ │ │ } │
|
|
@@ -374,7 +376,7 @@ TypeBox provides modifiers that can be applied to an objects properties. This al
|
|
|
374
376
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
375
377
|
│ const T = Type.Object({ │ type T = { │ const T = { │
|
|
376
378
|
│ name: Type.ReadonlyOptional( │ readonly name?: string │ type: 'object', │
|
|
377
|
-
│ Type.String()
|
|
379
|
+
│ Type.String() │ } │ properties: { │
|
|
378
380
|
│ ) │ │ name: { │
|
|
379
381
|
│ }) │ │ type: 'string' │
|
|
380
382
|
│ │ │ } │
|
|
@@ -490,28 +492,28 @@ Use `Type.Recursive(...)` to create recursive types.
|
|
|
490
492
|
|
|
491
493
|
```typescript
|
|
492
494
|
const Node = Type.Recursive(Node => Type.Object({ // const Node = {
|
|
493
|
-
id: Type.String(), // $id:
|
|
494
|
-
nodes: Type.Array(Node)
|
|
495
|
+
id: Type.String(), // $id: 'Node',
|
|
496
|
+
nodes: Type.Array(Node) // type: 'object',
|
|
495
497
|
}), { $id: 'Node' }) // properties: {
|
|
496
498
|
// id: {
|
|
497
|
-
//
|
|
499
|
+
// type: 'string'
|
|
498
500
|
// },
|
|
499
501
|
// nodes: {
|
|
500
|
-
// type:
|
|
502
|
+
// type: 'array',
|
|
501
503
|
// items: {
|
|
502
|
-
// $ref:
|
|
504
|
+
// $ref: 'Node'
|
|
503
505
|
// }
|
|
504
506
|
// }
|
|
505
507
|
// },
|
|
506
508
|
// required: [
|
|
507
|
-
//
|
|
508
|
-
//
|
|
509
|
+
// 'id',
|
|
510
|
+
// 'nodes'
|
|
509
511
|
// ]
|
|
510
512
|
// }
|
|
511
513
|
|
|
512
514
|
type Node = Static<typeof Node> // type Node = {
|
|
513
515
|
// id: string
|
|
514
|
-
// nodes:
|
|
516
|
+
// nodes: Node[]
|
|
515
517
|
// }
|
|
516
518
|
|
|
517
519
|
function test(node: Node) {
|
|
@@ -620,41 +622,41 @@ The following table shows the TypeBox mappings between TypeScript and JSON schem
|
|
|
620
622
|
|
|
621
623
|
```typescript
|
|
622
624
|
┌────────────────────────────────┬─────────────────────────────┬────────────────────────────────┐
|
|
623
|
-
│ TypeBox │ TypeScript │
|
|
625
|
+
│ TypeBox │ TypeScript │ JSON Schema │
|
|
624
626
|
│ │ │ │
|
|
625
627
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
626
628
|
│ const T = Conditional.Extends( │ type T = │ const T = { │
|
|
627
|
-
│ Type.String(), │ string extends number │ const: false
|
|
629
|
+
│ Type.String(), │ string extends number │ const: false, │
|
|
628
630
|
│ Type.Number(), │ true : false │ type: 'boolean' │
|
|
629
|
-
│ Type.Literal(true)
|
|
631
|
+
│ Type.Literal(true), │ │ } │
|
|
630
632
|
│ Type.Literal(false) │ │ │
|
|
631
633
|
│ ) │ │ │
|
|
632
634
|
│ │ │ │
|
|
633
635
|
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
634
|
-
│ const T = Conditional.Exclude( │ type T = Exclude< │ const T = { │
|
|
635
|
-
│ Type.Union([ │ 'a' | 'b' | 'c', │ anyOf: [{ │
|
|
636
|
-
│ Type.Literal('a') │ 'a' │ const: 'b' │
|
|
637
|
-
│ Type.Literal('b') │ > │ type: 'string' │
|
|
638
|
-
│ Type.Literal('c') │ │ }, { │
|
|
639
|
-
│ ]), │ │ const: 'c' │
|
|
640
|
-
│ Type.Union([ │ │ type: 'string' │
|
|
641
|
-
│ Type.Literal('a') │ │ }] │
|
|
642
|
-
│ ]) │ │ } │
|
|
643
|
-
│ ) │ │ │
|
|
644
|
-
│ │ │ │
|
|
645
|
-
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
646
636
|
│ const T = Conditional.Extract( │ type T = Extract< │ const T = { │
|
|
647
637
|
│ Type.Union([ │ 'a' | 'b' | 'c', │ anyOf: [{ │
|
|
648
|
-
│ Type.Literal('a')
|
|
649
|
-
│ Type.Literal('b')
|
|
638
|
+
│ Type.Literal('a'), │ 'a' | 'f' │ const: 'a' │
|
|
639
|
+
│ Type.Literal('b'), │ > │ type: 'string' │
|
|
650
640
|
│ Type.Literal('c') │ │ }] │
|
|
651
641
|
│ ]), │ │ } │
|
|
652
642
|
│ Type.Union([ │ │ │
|
|
653
|
-
│ Type.Literal('a')
|
|
643
|
+
│ Type.Literal('a'), │ │ │
|
|
654
644
|
│ Type.Literal('f') │ │ │
|
|
655
645
|
│ ]) │ │ │
|
|
656
646
|
│ ) │ │ │
|
|
657
647
|
│ │ │ │
|
|
648
|
+
├────────────────────────────────┼─────────────────────────────┼────────────────────────────────┤
|
|
649
|
+
│ const T = Conditional.Exclude( │ type T = Exclude< │ const T = { │
|
|
650
|
+
│ Type.Union([ │ 'a' | 'b' | 'c', │ anyOf: [{ │
|
|
651
|
+
│ Type.Literal('a'), │ 'a' │ const: 'b', │
|
|
652
|
+
│ Type.Literal('b'), │ > │ type: 'string' │
|
|
653
|
+
│ Type.Literal('c') │ │ }, { │
|
|
654
|
+
│ ]), │ │ const: 'c', │
|
|
655
|
+
│ Type.Union([ │ │ type: 'string' │
|
|
656
|
+
│ Type.Literal('a') │ │ }] │
|
|
657
|
+
│ ]) │ │ } │
|
|
658
|
+
│ ) │ │ │
|
|
659
|
+
│ │ │ │
|
|
658
660
|
└────────────────────────────────┴─────────────────────────────┴────────────────────────────────┘
|
|
659
661
|
```
|
|
660
662
|
|
|
@@ -670,12 +672,12 @@ import { Type } from '@sinclair/typebox'
|
|
|
670
672
|
|
|
671
673
|
const T = Type.Object({
|
|
672
674
|
x: Type.Number({ default: 1 }),
|
|
673
|
-
y: Type.Number()
|
|
675
|
+
y: Type.Number()
|
|
674
676
|
})
|
|
675
677
|
|
|
676
678
|
const V = Value.Create(T) // const V = {
|
|
677
679
|
// x: 1,
|
|
678
|
-
// y: 0
|
|
680
|
+
// y: 0
|
|
679
681
|
// }
|
|
680
682
|
```
|
|
681
683
|
Use `Value.Cast(...)` to cast a value into a given type.
|
|
@@ -747,7 +749,7 @@ const U = Type.Strict(T) // const U = {
|
|
|
747
749
|
|
|
748
750
|
## Validation
|
|
749
751
|
|
|
750
|
-
TypeBox schemas target JSON Schema draft 6 so any validator capable of draft 6 should be fine. A good library to use for validation in JavaScript environments is [
|
|
752
|
+
TypeBox schemas target JSON Schema draft 6 so any validator capable of draft 6 should be fine. A good library to use for validation in JavaScript environments is [Ajv](https://www.npmjs.com/package/ajv). The following example shows setting up Ajv to work with TypeBox.
|
|
751
753
|
|
|
752
754
|
```bash
|
|
753
755
|
$ npm install ajv ajv-formats --save
|
|
@@ -756,7 +758,7 @@ $ npm install ajv ajv-formats --save
|
|
|
756
758
|
```typescript
|
|
757
759
|
//--------------------------------------------------------------------------------------------
|
|
758
760
|
//
|
|
759
|
-
// Import TypeBox and
|
|
761
|
+
// Import TypeBox and Ajv
|
|
760
762
|
//
|
|
761
763
|
//--------------------------------------------------------------------------------------------
|
|
762
764
|
|
|
@@ -766,7 +768,7 @@ import Ajv from 'ajv'
|
|
|
766
768
|
|
|
767
769
|
//--------------------------------------------------------------------------------------------
|
|
768
770
|
//
|
|
769
|
-
// Setup
|
|
771
|
+
// Setup Ajv validator with the following options and formats
|
|
770
772
|
//
|
|
771
773
|
//--------------------------------------------------------------------------------------------
|
|
772
774
|
|
|
@@ -796,7 +798,7 @@ const ajv = addFormats(new Ajv({}), [
|
|
|
796
798
|
const T = Type.Object({
|
|
797
799
|
x: Type.Number(),
|
|
798
800
|
y: Type.Number(),
|
|
799
|
-
z: Type.Number()
|
|
801
|
+
z: Type.Number()
|
|
800
802
|
})
|
|
801
803
|
|
|
802
804
|
//--------------------------------------------------------------------------------------------
|
|
@@ -808,13 +810,13 @@ const T = Type.Object({
|
|
|
808
810
|
const R = ajv.validate(T, { x: 1, y: 2, z: 3 }) // const R = true
|
|
809
811
|
```
|
|
810
812
|
|
|
811
|
-
Please refer to the official
|
|
813
|
+
Please refer to the official Ajv [documentation](https://ajv.js.org/guide/getting-started.html) for additional information on using Ajv.
|
|
812
814
|
|
|
813
815
|
<a name="Compiler"></a>
|
|
814
816
|
|
|
815
817
|
## Compiler
|
|
816
818
|
|
|
817
|
-
TypeBox provides an optional high performance runtime type checker that can be used in applications that require extremely fast validation. This type checker is optimized for TypeBox types only whose schematics are known in advance. If defining custom schemas with `Type.Unsafe<T>` please consider
|
|
819
|
+
TypeBox provides an optional high performance runtime type checker that can be used in applications that require extremely fast validation. This type checker is optimized for TypeBox types only whose schematics are known in advance. If defining custom schemas with `Type.Unsafe<T>` please consider Ajv.
|
|
818
820
|
|
|
819
821
|
The following demonstrates its use.
|
|
820
822
|
|
|
@@ -872,75 +874,78 @@ console.log(C.Code()) // return function check(va
|
|
|
872
874
|
// }
|
|
873
875
|
```
|
|
874
876
|
|
|
875
|
-
|
|
877
|
+
## Benchmark
|
|
876
878
|
|
|
877
|
-
This project maintains benchmarks that measure
|
|
879
|
+
This project maintains benchmarks that measure Ajv and TypeCompiler validation and compilation performance. These benchmarks can be run locally by cloning this repository and running `npm run benchmark`. Results show against Ajv version 8.11.0.
|
|
878
880
|
|
|
879
|
-
|
|
881
|
+
### Validate
|
|
880
882
|
|
|
881
|
-
This benchmark measures
|
|
883
|
+
This benchmark measures validation performance for varying types. You can review this benchmark [here](https://github.com/sinclairzx81/typebox/blob/master/benchmark/check.ts).
|
|
882
884
|
|
|
883
885
|
```typescript
|
|
884
|
-
|
|
885
|
-
│ (index) │ Iterations │
|
|
886
|
-
|
|
887
|
-
│ Number │ 16000000 │ '
|
|
888
|
-
│ String │ 16000000 │ '
|
|
889
|
-
│ Boolean │ 16000000 │ '
|
|
890
|
-
│ Null │ 16000000 │ '
|
|
891
|
-
│ RegEx │ 16000000 │ '
|
|
892
|
-
│ ObjectA │ 16000000 │ '
|
|
893
|
-
│ ObjectB │ 16000000 │ '
|
|
894
|
-
│ Tuple │ 16000000 │ '
|
|
895
|
-
│ Union │ 16000000 │ '
|
|
896
|
-
│ Recursive │ 16000000 │ '
|
|
897
|
-
│ Vector4 │ 16000000 │ '
|
|
898
|
-
│ Matrix4 │ 16000000 │ '
|
|
899
|
-
│ Literal_String │ 16000000 │ '
|
|
900
|
-
│ Literal_Number │ 16000000 │ '
|
|
901
|
-
│ Literal_Boolean │ 16000000 │ '
|
|
902
|
-
│ Array_Number │ 16000000 │ '
|
|
903
|
-
│ Array_String │ 16000000 │ '
|
|
904
|
-
│ Array_Boolean │ 16000000 │ '
|
|
905
|
-
│ Array_ObjectA │ 16000000 │ '
|
|
906
|
-
│ Array_ObjectB │ 16000000 │ '
|
|
907
|
-
│ Array_Tuple │ 16000000 │ '
|
|
908
|
-
│
|
|
909
|
-
│
|
|
910
|
-
|
|
886
|
+
┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┐
|
|
887
|
+
│ (index) │ Iterations │ Ajv │ TypeCompiler │ Performance │
|
|
888
|
+
├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┤
|
|
889
|
+
│ Number │ 16000000 │ ' 73 ms' │ ' 65 ms' │ ' 1.12 x' │
|
|
890
|
+
│ String │ 16000000 │ ' 281 ms' │ ' 161 ms' │ ' 1.75 x' │
|
|
891
|
+
│ Boolean │ 16000000 │ ' 302 ms' │ ' 151 ms' │ ' 2.00 x' │
|
|
892
|
+
│ Null │ 16000000 │ ' 281 ms' │ ' 149 ms' │ ' 1.89 x' │
|
|
893
|
+
│ RegEx │ 16000000 │ ' 689 ms' │ ' 550 ms' │ ' 1.25 x' │
|
|
894
|
+
│ ObjectA │ 16000000 │ ' 470 ms' │ ' 311 ms' │ ' 1.51 x' │
|
|
895
|
+
│ ObjectB │ 16000000 │ ' 667 ms' │ ' 556 ms' │ ' 1.20 x' │
|
|
896
|
+
│ Tuple │ 16000000 │ ' 362 ms' │ ' 190 ms' │ ' 1.91 x' │
|
|
897
|
+
│ Union │ 16000000 │ ' 387 ms' │ ' 209 ms' │ ' 1.85 x' │
|
|
898
|
+
│ Recursive │ 16000000 │ ' 6327 ms' │ ' 2773 ms' │ ' 2.28 x' │
|
|
899
|
+
│ Vector4 │ 16000000 │ ' 362 ms' │ ' 172 ms' │ ' 2.10 x' │
|
|
900
|
+
│ Matrix4 │ 16000000 │ ' 607 ms' │ ' 418 ms' │ ' 1.45 x' │
|
|
901
|
+
│ Literal_String │ 16000000 │ ' 314 ms' │ ' 151 ms' │ ' 2.08 x' │
|
|
902
|
+
│ Literal_Number │ 16000000 │ ' 281 ms' │ ' 147 ms' │ ' 1.91 x' │
|
|
903
|
+
│ Literal_Boolean │ 16000000 │ ' 289 ms' │ ' 148 ms' │ ' 1.95 x' │
|
|
904
|
+
│ Array_Number │ 16000000 │ ' 475 ms' │ ' 230 ms' │ ' 2.07 x' │
|
|
905
|
+
│ Array_String │ 16000000 │ ' 463 ms' │ ' 297 ms' │ ' 1.56 x' │
|
|
906
|
+
│ Array_Boolean │ 16000000 │ ' 521 ms' │ ' 348 ms' │ ' 1.50 x' │
|
|
907
|
+
│ Array_ObjectA │ 16000000 │ ' 43842 ms' │ ' 28375 ms' │ ' 1.55 x' │
|
|
908
|
+
│ Array_ObjectB │ 16000000 │ ' 45055 ms' │ ' 32882 ms' │ ' 1.37 x' │
|
|
909
|
+
│ Array_Tuple │ 16000000 │ ' 1424 ms' │ ' 1105 ms' │ ' 1.29 x' │
|
|
910
|
+
│ Array_Union │ 16000000 │ ' 3505 ms' │ ' 1350 ms' │ ' 2.60 x' │
|
|
911
|
+
│ Array_Recursive │ 16000000 │ ' 117087 ms' │ ' 42982 ms' │ ' 2.72 x' │
|
|
912
|
+
│ Array_Vector4 │ 16000000 │ ' 1500 ms' │ ' 817 ms' │ ' 1.84 x' │
|
|
913
|
+
│ Array_Matrix4 │ 16000000 │ ' 6126 ms' │ ' 4965 ms' │ ' 1.23 x' │
|
|
914
|
+
└──────────────────┴────────────┴──────────────┴──────────────┴──────────────┘
|
|
911
915
|
```
|
|
912
916
|
|
|
913
|
-
|
|
917
|
+
### Compile
|
|
914
918
|
|
|
915
|
-
This benchmark measures
|
|
919
|
+
This benchmark measures compilation performance for varying types. You can review this benchmark [here](https://github.com/sinclairzx81/typebox/blob/master/benchmark/compile.ts).
|
|
916
920
|
|
|
917
921
|
```typescript
|
|
918
|
-
|
|
919
|
-
│ (index) │ Iterations │
|
|
920
|
-
|
|
921
|
-
│ Number │ 2000 │ '
|
|
922
|
-
│ String │ 2000 │ '
|
|
923
|
-
│ Boolean │ 2000 │ '
|
|
924
|
-
│ Null │ 2000 │ '
|
|
925
|
-
│ RegEx │ 2000 │ '
|
|
926
|
-
│ ObjectA │ 2000 │ '
|
|
927
|
-
│ ObjectB │ 2000 │ '
|
|
928
|
-
│ Tuple │ 2000 │ '
|
|
929
|
-
│ Union │ 2000 │ '
|
|
930
|
-
│ Vector4 │ 2000 │ '
|
|
931
|
-
│ Matrix4 │ 2000 │ '
|
|
932
|
-
│ Literal_String │ 2000 │ '
|
|
933
|
-
│ Literal_Number │ 2000 │ '
|
|
934
|
-
│ Literal_Boolean │ 2000 │ '
|
|
935
|
-
│ Array_Number │ 2000 │ '
|
|
936
|
-
│ Array_String │ 2000 │ '
|
|
937
|
-
│ Array_Boolean │ 2000 │ '
|
|
938
|
-
│ Array_ObjectA │ 2000 │ '
|
|
939
|
-
│ Array_ObjectB │ 2000 │ '
|
|
940
|
-
│ Array_Tuple │ 2000 │ '
|
|
941
|
-
│
|
|
942
|
-
│
|
|
943
|
-
|
|
922
|
+
┌──────────────────┬────────────┬──────────────┬──────────────┬──────────────┐
|
|
923
|
+
│ (index) │ Iterations │ Ajv │ TypeCompiler │ Performance │
|
|
924
|
+
├──────────────────┼────────────┼──────────────┼──────────────┼──────────────┤
|
|
925
|
+
│ Number │ 2000 │ ' 387 ms' │ ' 7 ms' │ ' 55.29 x' │
|
|
926
|
+
│ String │ 2000 │ ' 340 ms' │ ' 6 ms' │ ' 56.67 x' │
|
|
927
|
+
│ Boolean │ 2000 │ ' 314 ms' │ ' 5 ms' │ ' 62.80 x' │
|
|
928
|
+
│ Null │ 2000 │ ' 259 ms' │ ' 5 ms' │ ' 51.80 x' │
|
|
929
|
+
│ RegEx │ 2000 │ ' 491 ms' │ ' 7 ms' │ ' 70.14 x' │
|
|
930
|
+
│ ObjectA │ 2000 │ ' 2850 ms' │ ' 26 ms' │ ' 109.62 x' │
|
|
931
|
+
│ ObjectB │ 2000 │ ' 2989 ms' │ ' 22 ms' │ ' 135.86 x' │
|
|
932
|
+
│ Tuple │ 2000 │ ' 1283 ms' │ ' 17 ms' │ ' 75.47 x' │
|
|
933
|
+
│ Union │ 2000 │ ' 1292 ms' │ ' 16 ms' │ ' 80.75 x' │
|
|
934
|
+
│ Vector4 │ 2000 │ ' 1588 ms' │ ' 12 ms' │ ' 132.33 x' │
|
|
935
|
+
│ Matrix4 │ 2000 │ ' 934 ms' │ ' 7 ms' │ ' 133.43 x' │
|
|
936
|
+
│ Literal_String │ 2000 │ ' 340 ms' │ ' 5 ms' │ ' 68.00 x' │
|
|
937
|
+
│ Literal_Number │ 2000 │ ' 402 ms' │ ' 4 ms' │ ' 100.50 x' │
|
|
938
|
+
│ Literal_Boolean │ 2000 │ ' 381 ms' │ ' 6 ms' │ ' 63.50 x' │
|
|
939
|
+
│ Array_Number │ 2000 │ ' 750 ms' │ ' 8 ms' │ ' 93.75 x' │
|
|
940
|
+
│ Array_String │ 2000 │ ' 760 ms' │ ' 6 ms' │ ' 126.67 x' │
|
|
941
|
+
│ Array_Boolean │ 2000 │ ' 796 ms' │ ' 7 ms' │ ' 113.71 x' │
|
|
942
|
+
│ Array_ObjectA │ 2000 │ ' 3617 ms' │ ' 26 ms' │ ' 139.12 x' │
|
|
943
|
+
│ Array_ObjectB │ 2000 │ ' 3823 ms' │ ' 26 ms' │ ' 147.04 x' │
|
|
944
|
+
│ Array_Tuple │ 2000 │ ' 2263 ms' │ ' 13 ms' │ ' 174.08 x' │
|
|
945
|
+
│ Array_Union │ 2000 │ ' 1725 ms' │ ' 16 ms' │ ' 107.81 x' │
|
|
946
|
+
│ Array_Vector4 │ 2000 │ ' 2445 ms' │ ' 14 ms' │ ' 174.64 x' │
|
|
947
|
+
│ Array_Matrix4 │ 2000 │ ' 1638 ms' │ ' 11 ms' │ ' 148.91 x' │
|
|
948
|
+
└──────────────────┴────────────┴──────────────┴──────────────┴──────────────┘
|
|
944
949
|
```
|
|
945
950
|
|
|
946
951
|
<a name="Contribute"></a>
|
package/typebox.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const Kind: unique symbol;
|
|
2
|
+
export declare const Hint: unique symbol;
|
|
2
3
|
export declare const Modifier: unique symbol;
|
|
3
4
|
export declare type TModifier = TReadonlyOptional<TSchema> | TOptional<TSchema> | TReadonly<TSchema>;
|
|
4
5
|
export declare type TReadonly<T extends TSchema> = T & {
|
|
@@ -10,10 +11,6 @@ export declare type TOptional<T extends TSchema> = T & {
|
|
|
10
11
|
export declare type TReadonlyOptional<T extends TSchema> = T & {
|
|
11
12
|
[Modifier]: 'ReadonlyOptional';
|
|
12
13
|
};
|
|
13
|
-
export interface DesignType {
|
|
14
|
-
type: string;
|
|
15
|
-
[props: string]: any;
|
|
16
|
-
}
|
|
17
14
|
export interface SchemaOptions {
|
|
18
15
|
$schema?: string;
|
|
19
16
|
/** Id for this schema */
|
|
@@ -30,6 +27,7 @@ export interface SchemaOptions {
|
|
|
30
27
|
}
|
|
31
28
|
export interface TSchema extends SchemaOptions {
|
|
32
29
|
[Kind]: string;
|
|
30
|
+
[Hint]?: string;
|
|
33
31
|
[Modifier]?: string;
|
|
34
32
|
params: unknown[];
|
|
35
33
|
static: unknown;
|
|
@@ -109,9 +107,12 @@ export interface TIntersect<T extends TObject[] = TObject[]> extends TObject {
|
|
|
109
107
|
static: IntersectReduce<unknown, IntersectEvaluate<T, this['params']>>;
|
|
110
108
|
properties: Record<keyof IntersectReduce<unknown, IntersectEvaluate<T, this['params']>>, TSchema>;
|
|
111
109
|
}
|
|
112
|
-
declare type UnionToIntersect<U> = (U extends unknown ? (arg: U) => 0 : never) extends (arg: infer I) => 0 ? I : never;
|
|
113
|
-
declare type UnionLast<U> = UnionToIntersect<U extends unknown ? (x: U) => 0 : never> extends (x: infer L) => 0 ? L : never;
|
|
114
|
-
declare type UnionToTuple<U, L = UnionLast<U>> = [U] extends [never] ? [] : [...UnionToTuple<Exclude<U, L>>, L];
|
|
110
|
+
export declare type UnionToIntersect<U> = (U extends unknown ? (arg: U) => 0 : never) extends (arg: infer I) => 0 ? I : never;
|
|
111
|
+
export declare type UnionLast<U> = UnionToIntersect<U extends unknown ? (x: U) => 0 : never> extends (x: infer L) => 0 ? L : never;
|
|
112
|
+
export declare type UnionToTuple<U, L = UnionLast<U>> = [U] extends [never] ? [] : [...UnionToTuple<Exclude<U, L>>, L];
|
|
113
|
+
export declare type UnionStringLiteralToTuple<T> = T extends TUnion<infer L> ? {
|
|
114
|
+
[I in keyof L]: L[I] extends TLiteral<infer C> ? C : never;
|
|
115
|
+
} : never;
|
|
115
116
|
export declare type TKeyOf<T extends TObject> = {
|
|
116
117
|
[K in ObjectPropertyKeys<T>]: TLiteral<K>;
|
|
117
118
|
} extends infer R ? UnionToTuple<R[keyof R]> : never;
|
|
@@ -179,10 +180,9 @@ export interface TOmit<T extends TObject, Properties extends ObjectPropertyKeys<
|
|
|
179
180
|
export interface TPartial<T extends TObject> extends TObject {
|
|
180
181
|
static: Partial<Static<T, this['params']>>;
|
|
181
182
|
}
|
|
182
|
-
export
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}
|
|
183
|
+
export declare type TPick<T extends TObject, Properties extends ObjectPropertyKeys<T>[]> = TObject<{
|
|
184
|
+
[K in Properties[number]]: T['properties'][K];
|
|
185
|
+
}>;
|
|
186
186
|
export interface TPromise<T extends TSchema = TSchema> extends TSchema {
|
|
187
187
|
[Kind]: 'Promise';
|
|
188
188
|
static: Promise<Static<T, this['params']>>;
|
|
@@ -230,6 +230,7 @@ export interface TString extends TSchema, StringOptions<string> {
|
|
|
230
230
|
static: string;
|
|
231
231
|
type: 'string';
|
|
232
232
|
}
|
|
233
|
+
export declare type TupleToArray<T extends TTuple<TSchema[]>> = T extends TTuple<infer R> ? R : never;
|
|
233
234
|
export interface TTuple<T extends TSchema[] = TSchema[]> extends TSchema {
|
|
234
235
|
[Kind]: 'Tuple';
|
|
235
236
|
static: {
|
|
@@ -300,11 +301,15 @@ export declare class TypeBuilder {
|
|
|
300
301
|
/** Creates a tuple type from this constructors parameters */
|
|
301
302
|
ConstructorParameters<T extends TConstructor<any[], any>>(schema: T, options?: SchemaOptions): TConstructorParameters<T>;
|
|
302
303
|
/** Creates a constructor type */
|
|
304
|
+
Constructor<T extends TTuple<TSchema[]>, U extends TSchema>(parameters: T, returns: U, options?: SchemaOptions): TConstructor<TupleToArray<T>, U>;
|
|
305
|
+
/** Creates a constructor type */
|
|
303
306
|
Constructor<T extends TSchema[], U extends TSchema>(parameters: [...T], returns: U, options?: SchemaOptions): TConstructor<T, U>;
|
|
304
307
|
/** Creates a enum type */
|
|
305
308
|
Enum<T extends Record<string, string | number>>(item: T, options?: SchemaOptions): TEnum<T>;
|
|
306
309
|
/** Creates a function type */
|
|
307
|
-
Function<T extends
|
|
310
|
+
Function<T extends TTuple<TSchema[]>, U extends TSchema>(parameters: T, returns: U, options?: SchemaOptions): TFunction<TupleToArray<T>, U>;
|
|
311
|
+
/** Creates a function type */
|
|
312
|
+
Function<T extends TSchema[], U extends TSchema>(parameters: [...T], returns: U, options?: SchemaOptions): TFunction<T, U>;
|
|
308
313
|
/** Creates a type from this constructors instance type */
|
|
309
314
|
InstanceType<T extends TConstructor<any[], any>>(schema: T, options?: SchemaOptions): TInstanceType<T>;
|
|
310
315
|
/** Creates a integer type */
|
|
@@ -322,13 +327,17 @@ export declare class TypeBuilder {
|
|
|
322
327
|
/** Creates an object type with the given properties */
|
|
323
328
|
Object<T extends TProperties>(properties: T, options?: ObjectOptions): TObject<T>;
|
|
324
329
|
/** Creates a new object whose properties are omitted from the given object */
|
|
325
|
-
Omit<T extends TObject,
|
|
330
|
+
Omit<T extends TObject, K extends TUnion<TLiteral<string>[]>>(schema: T, keys: K, options?: ObjectOptions): TOmit<T, UnionStringLiteralToTuple<K>>;
|
|
331
|
+
/** Creates a new object whose properties are omitted from the given object */
|
|
332
|
+
Omit<T extends TObject, K extends ObjectPropertyKeys<T>[]>(schema: T, keys: [...K], options?: ObjectOptions): TOmit<T, K>;
|
|
326
333
|
/** Creates a tuple type from this functions parameters */
|
|
327
334
|
Parameters<T extends TFunction<any[], any>>(schema: T, options?: SchemaOptions): TParameters<T>;
|
|
328
335
|
/** Creates an object type whose properties are all optional */
|
|
329
336
|
Partial<T extends TObject>(schema: T, options?: ObjectOptions): TPartial<T>;
|
|
330
|
-
/** Creates a
|
|
331
|
-
Pick<T extends TObject,
|
|
337
|
+
/** Creates a object whose properties are picked from the given object */
|
|
338
|
+
Pick<T extends TObject, K extends TUnion<TLiteral<string>[]>>(schema: T, keys: K, options?: ObjectOptions): TPick<T, UnionStringLiteralToTuple<K>>;
|
|
339
|
+
/** Creates a object whose properties are picked from the given object */
|
|
340
|
+
Pick<T extends TObject, K extends ObjectPropertyKeys<T>[]>(schema: T, keys: [...K], options?: ObjectOptions): TPick<T, K>;
|
|
332
341
|
/** Creates a promise type. This type cannot be represented in schema. */
|
|
333
342
|
Promise<T extends TSchema>(item: T, options?: SchemaOptions): TPromise<T>;
|
|
334
343
|
/** Creates an object whose properties are derived from the given string literal union. */
|
|
@@ -370,4 +379,3 @@ export declare class TypeBuilder {
|
|
|
370
379
|
}
|
|
371
380
|
/** JSON Schema Type Builder with Static Type Resolution for TypeScript */
|
|
372
381
|
export declare const Type: TypeBuilder;
|
|
373
|
-
export {};
|
package/typebox.js
CHANGED
|
@@ -27,11 +27,12 @@ THE SOFTWARE.
|
|
|
27
27
|
|
|
28
28
|
---------------------------------------------------------------------------*/
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
exports.Type = exports.TypeBuilder = exports.Modifier = exports.Kind = void 0;
|
|
30
|
+
exports.Type = exports.TypeBuilder = exports.Modifier = exports.Hint = exports.Kind = void 0;
|
|
31
31
|
// --------------------------------------------------------------------------
|
|
32
32
|
// Symbols
|
|
33
33
|
// --------------------------------------------------------------------------
|
|
34
34
|
exports.Kind = Symbol.for('TypeBox.Kind');
|
|
35
|
+
exports.Hint = Symbol.for('TypeBox.Hint');
|
|
35
36
|
exports.Modifier = Symbol.for('TypeBox.Modifier');
|
|
36
37
|
// --------------------------------------------------------------------------
|
|
37
38
|
// TypeBuilder
|
|
@@ -74,7 +75,16 @@ class TypeBuilder {
|
|
|
74
75
|
}
|
|
75
76
|
/** Creates a constructor type */
|
|
76
77
|
Constructor(parameters, returns, options = {}) {
|
|
77
|
-
|
|
78
|
+
if (parameters[exports.Kind] === 'Tuple') {
|
|
79
|
+
const inner = parameters.items === undefined ? [] : parameters.items;
|
|
80
|
+
return this.Create({ ...options, [exports.Kind]: 'Constructor', type: 'constructor', parameters: inner, returns });
|
|
81
|
+
}
|
|
82
|
+
else if (globalThis.Array.isArray(parameters)) {
|
|
83
|
+
return this.Create({ ...options, [exports.Kind]: 'Constructor', type: 'constructor', parameters, returns });
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
throw new Error('TypeBuilder.Constructor: Invalid parameters');
|
|
87
|
+
}
|
|
78
88
|
}
|
|
79
89
|
/** Creates a enum type */
|
|
80
90
|
Enum(item, options = {}) {
|
|
@@ -82,11 +92,20 @@ class TypeBuilder {
|
|
|
82
92
|
.filter((key) => isNaN(key))
|
|
83
93
|
.map((key) => item[key]);
|
|
84
94
|
const anyOf = values.map((value) => (typeof value === 'string' ? { [exports.Kind]: 'Literal', type: 'string', const: value } : { [exports.Kind]: 'Literal', type: 'number', const: value }));
|
|
85
|
-
return this.Create({ ...options, [exports.Kind]: 'Union', anyOf });
|
|
95
|
+
return this.Create({ ...options, [exports.Kind]: 'Union', [exports.Hint]: 'Enum', anyOf });
|
|
86
96
|
}
|
|
87
97
|
/** Creates a function type */
|
|
88
98
|
Function(parameters, returns, options = {}) {
|
|
89
|
-
|
|
99
|
+
if (parameters[exports.Kind] === 'Tuple') {
|
|
100
|
+
const inner = parameters.items === undefined ? [] : parameters.items;
|
|
101
|
+
return this.Create({ ...options, [exports.Kind]: 'Function', type: 'function', parameters: inner, returns });
|
|
102
|
+
}
|
|
103
|
+
else if (globalThis.Array.isArray(parameters)) {
|
|
104
|
+
return this.Create({ ...options, [exports.Kind]: 'Function', type: 'function', parameters, returns });
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
throw new Error('TypeBuilder.Function: Invalid parameters');
|
|
108
|
+
}
|
|
90
109
|
}
|
|
91
110
|
/** Creates a type from this constructors instance type */
|
|
92
111
|
InstanceType(schema, options = {}) {
|
|
@@ -128,7 +147,7 @@ class TypeBuilder {
|
|
|
128
147
|
/** Creates a keyof type */
|
|
129
148
|
KeyOf(object, options = {}) {
|
|
130
149
|
const items = Object.keys(object.properties).map((key) => this.Create({ ...options, [exports.Kind]: 'Literal', type: 'string', const: key }));
|
|
131
|
-
return this.Create({ ...options, [exports.Kind]: 'Union', anyOf: items });
|
|
150
|
+
return this.Create({ ...options, [exports.Kind]: 'Union', [exports.Hint]: 'KeyOf', anyOf: items });
|
|
132
151
|
}
|
|
133
152
|
/** Creates a literal type. */
|
|
134
153
|
Literal(value, options = {}) {
|
|
@@ -160,10 +179,11 @@ class TypeBuilder {
|
|
|
160
179
|
}
|
|
161
180
|
/** Creates a new object whose properties are omitted from the given object */
|
|
162
181
|
Omit(schema, keys, options = {}) {
|
|
163
|
-
const
|
|
164
|
-
next
|
|
182
|
+
const select = keys[exports.Kind] === 'Union' ? keys.anyOf.map((schema) => schema.const) : keys;
|
|
183
|
+
const next = { ...this.Clone(schema), ...options, [exports.Hint]: 'Omit' };
|
|
184
|
+
next.required = next.required ? next.required.filter((key) => !select.includes(key)) : undefined;
|
|
165
185
|
for (const key of Object.keys(next.properties)) {
|
|
166
|
-
if (
|
|
186
|
+
if (select.includes(key))
|
|
167
187
|
delete next.properties[key];
|
|
168
188
|
}
|
|
169
189
|
return this.Create(next);
|
|
@@ -174,7 +194,7 @@ class TypeBuilder {
|
|
|
174
194
|
}
|
|
175
195
|
/** Creates an object type whose properties are all optional */
|
|
176
196
|
Partial(schema, options = {}) {
|
|
177
|
-
const next = { ...this.Clone(schema), ...options };
|
|
197
|
+
const next = { ...this.Clone(schema), ...options, [exports.Hint]: 'Partial' };
|
|
178
198
|
delete next.required;
|
|
179
199
|
for (const key of Object.keys(next.properties)) {
|
|
180
200
|
const property = next.properties[key];
|
|
@@ -196,12 +216,13 @@ class TypeBuilder {
|
|
|
196
216
|
}
|
|
197
217
|
return this.Create(next);
|
|
198
218
|
}
|
|
199
|
-
/** Creates a
|
|
219
|
+
/** Creates a object whose properties are picked from the given object */
|
|
200
220
|
Pick(schema, keys, options = {}) {
|
|
201
|
-
const
|
|
202
|
-
next
|
|
221
|
+
const select = keys[exports.Kind] === 'Union' ? keys.anyOf.map((schema) => schema.const) : keys;
|
|
222
|
+
const next = { ...this.Clone(schema), ...options, [exports.Hint]: 'Pick' };
|
|
223
|
+
next.required = next.required ? next.required.filter((key) => select.includes(key)) : undefined;
|
|
203
224
|
for (const key of Object.keys(next.properties)) {
|
|
204
|
-
if (!
|
|
225
|
+
if (!select.includes(key))
|
|
205
226
|
delete next.properties[key];
|
|
206
227
|
}
|
|
207
228
|
return this.Create(next);
|
|
@@ -216,7 +237,7 @@ class TypeBuilder {
|
|
|
216
237
|
if (key[exports.Kind] === 'Union') {
|
|
217
238
|
return this.Object(key.anyOf.reduce((acc, literal) => {
|
|
218
239
|
return { ...acc, [literal.const]: value };
|
|
219
|
-
}, {}), { ...options });
|
|
240
|
+
}, {}), { ...options, [exports.Hint]: 'Record' });
|
|
220
241
|
}
|
|
221
242
|
// otherwise return TRecord with patternProperties
|
|
222
243
|
const pattern = key[exports.Kind] === 'Number' ? '^(0|[1-9][0-9]*)$' : key[exports.Kind] === 'String' && key.pattern ? key.pattern : '^.*$';
|
|
@@ -239,7 +260,7 @@ class TypeBuilder {
|
|
|
239
260
|
/** Creates a reference schema */
|
|
240
261
|
Ref(schema, options = {}) {
|
|
241
262
|
if (schema.$id === undefined)
|
|
242
|
-
throw Error('
|
|
263
|
+
throw Error('TypeBuilder.Ref: Referenced schema must specify an $id');
|
|
243
264
|
return this.Create({ ...options, [exports.Kind]: 'Ref', $ref: schema.$id });
|
|
244
265
|
}
|
|
245
266
|
/** Creates a string type from a regular expression */
|
|
@@ -248,7 +269,7 @@ class TypeBuilder {
|
|
|
248
269
|
}
|
|
249
270
|
/** Creates an object type whose properties are all required */
|
|
250
271
|
Required(schema, options = {}) {
|
|
251
|
-
const next = { ...this.Clone(schema), ...options };
|
|
272
|
+
const next = { ...this.Clone(schema), ...options, [exports.Hint]: 'Required' };
|
|
252
273
|
next.required = Object.keys(next.properties);
|
|
253
274
|
for (const key of Object.keys(next.properties)) {
|
|
254
275
|
const property = next.properties[key];
|