@sinclair/typebox 0.20.6 → 0.22.0

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 (4) hide show
  1. package/package.json +13 -9
  2. package/readme.md +11 -11
  3. package/typebox.d.ts +162 -141
  4. package/typebox.js +63 -58
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinclair/typebox",
3
- "version": "0.20.6",
3
+ "version": "0.22.0",
4
4
  "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
5
5
  "keywords": [
6
6
  "json-schema",
@@ -20,17 +20,21 @@
20
20
  "clean": "hammer task clean",
21
21
  "build": "hammer task build",
22
22
  "example": "hammer task example",
23
- "test": "hammer task spec"
23
+ "spec": "hammer task spec",
24
+ "spec:types": "hammer task spec_types",
25
+ "spec:schemas": "hammer task spec_schemas",
26
+ "test": "npm run spec"
24
27
  },
25
28
  "devDependencies": {
26
- "@sinclair/hammer": "^0.15.7",
27
- "@types/chai": "^4.2.16",
28
- "@types/mocha": "^8.2.2",
29
- "@types/node": "^14.14.37",
30
- "ajv": "^8.6.2",
31
- "ajv-formats": "^2.0.2",
29
+ "@sinclair/hammer": "^0.15.8",
30
+ "@types/chai": "^4.2.22",
31
+ "@types/mocha": "^9.0.0",
32
+ "@types/node": "^16.11.9",
33
+ "ajv": "^8.8.2",
34
+ "ajv-formats": "^2.1.1",
32
35
  "chai": "^4.3.4",
33
- "mocha": "^9.1.2",
36
+ "mocha": "^9.1.3",
37
+ "tsd": "^0.19.0",
34
38
  "typescript": "^4.5.2"
35
39
  }
36
40
  }
package/readme.md CHANGED
@@ -447,12 +447,12 @@ const R = Type.Ref(T) // const R = {
447
447
  // }
448
448
  ```
449
449
 
450
- It can be helpful to organize shared referenced types under a common namespace. The `Type.Box(...)` function can be used to create a shared definition container for related types. The following creates a `Math3D` container and a `Vertex` structure that references types in the container.
450
+ It can be helpful to organize shared referenced types under a common namespace. The `Type.Namespace(...)` function can be used to create a shared definition container for related types. The following creates a `Math3D` container and a `Vertex` structure that references types in the container.
451
451
 
452
452
  ```typescript
453
- const Math3D = Type.Box({ // const Math3D = {
453
+ const Math3D = Type.Namespace({ // const Math3D = {
454
454
  Vector4: Type.Object({ // $id: 'Math3D',
455
- x: Type.Number(), // definitions: {
455
+ x: Type.Number(), // $defs: {
456
456
  y: Type.Number(), // Vector4: {
457
457
  z: Type.Number(), // type: 'object',
458
458
  w: Type.Number() // properties: {
@@ -486,9 +486,9 @@ const Math3D = Type.Box({ // const Math3D = {
486
486
  const Vertex = Type.Object({ // const Vertex = {
487
487
  position: Type.Ref(Math3D, 'Vector4'), // type: 'object',
488
488
  normal: Type.Ref(Math3D, 'Vector3'), // properties: {
489
- uv: Type.Ref(Math3D, 'Vector2') // position: { $ref: 'Math3D#/definitions/Vector4' },
490
- }) // normal: { $ref: 'Math3D#/definitions/Vector3' },
491
- // uv: { $ref: 'Math3D#/definitions/Vector2' }
489
+ uv: Type.Ref(Math3D, 'Vector2') // position: { $ref: 'Math3D#/$defs/Vector4' },
490
+ }) // normal: { $ref: 'Math3D#/$defs/Vector3' },
491
+ // uv: { $ref: 'Math3D#/$defs/Vector2' }
492
492
  // },
493
493
  // required: ['position', 'normal', 'uv']
494
494
  // }
@@ -503,8 +503,8 @@ Recursive types can be created with the `Type.Rec(...)` function. The following
503
503
  ```typescript
504
504
  const Node = Type.Rec(Self => Type.Object({ // const Node = {
505
505
  id: Type.String(), // $id: 'Node',
506
- nodes: Type.Array(Self), // $ref: 'Node#/definitions/self',
507
- }), { $id: 'Node' }) // definitions: {
506
+ nodes: Type.Array(Self), // $ref: 'Node#/$defs/self',
507
+ }), { $id: 'Node' }) // $defs: {
508
508
  // self: {
509
509
  // type: 'object',
510
510
  // properties: {
@@ -514,7 +514,7 @@ const Node = Type.Rec(Self => Type.Object({ // const Node = {
514
514
  // nodes: {
515
515
  // type: 'array',
516
516
  // items: {
517
- // $ref: 'Node#/definitions/self'
517
+ // $ref: 'Node#/$defs/self'
518
518
  // }
519
519
  // }
520
520
  // }
@@ -691,7 +691,7 @@ const ok = ajv.validate(User, {
691
691
 
692
692
  #### Reference Types
693
693
 
694
- Referenced types can be added to AJV with the `ajv.addSchema(...)` function. The following moves the `userId` and `email` property types into a `Type.Box(...)` and registers the box with AJV.
694
+ Referenced types can be added to AJV with the `ajv.addSchema(...)` function. The following moves the `userId` and `email` property types into a `Type.Namespace(...)` and registers the box with AJV.
695
695
 
696
696
  ```typescript
697
697
  //--------------------------------------------------------------------------------------------
@@ -700,7 +700,7 @@ Referenced types can be added to AJV with the `ajv.addSchema(...)` function. The
700
700
  //
701
701
  //--------------------------------------------------------------------------------------------
702
702
 
703
- const Shared = Type.Box({
703
+ const Shared = Type.Namespace({
704
704
  UserId: Type.String({ format: 'uuid' }),
705
705
  Email: Type.String({ format: 'email' })
706
706
  }, { $id: 'Shared' })
package/typebox.d.ts CHANGED
@@ -63,252 +63,273 @@ export declare type IntersectOptions = {
63
63
  export declare type ObjectOptions = {
64
64
  additionalProperties?: boolean;
65
65
  } & CustomOptions;
66
+ export declare type TDefinitions = {
67
+ [key: string]: TSchema;
68
+ };
69
+ export declare type TNamespace<T extends TDefinitions> = {
70
+ kind: typeof BoxKind;
71
+ $defs: T;
72
+ } & CustomOptions;
73
+ export interface TSchema {
74
+ 'typebox:output': unknown;
75
+ }
66
76
  export declare type TEnumType = Record<string, string | number>;
67
- export declare type TKey = string | number;
77
+ export declare type TKey = string | number | symbol;
68
78
  export declare type TValue = string | number | boolean;
69
- export declare type TRecordKey = TString | TNumber | TUnion<TLiteral<string | number>[]>;
79
+ export declare type TRecordKey = TString | TNumber | TKeyOf<any> | TUnion<any>;
70
80
  export declare type TEnumKey<T = TKey> = {
71
81
  type: 'number' | 'string';
72
82
  const: T;
73
83
  };
74
- export declare type TDefinitions = {
75
- [key: string]: TSchema;
76
- };
77
- export declare type TProperties = {
84
+ export interface TProperties {
78
85
  [key: string]: TSchema;
79
- };
80
- export declare type TBox<T extends TDefinitions> = {
81
- kind: typeof BoxKind;
82
- definitions: T;
83
- } & CustomOptions;
84
- export declare type TTuple<T extends TSchema[]> = {
86
+ }
87
+ export interface TRecord<K extends TRecordKey, T extends TSchema> extends TSchema, ObjectOptions {
88
+ 'typebox:output': StaticRecord<K, T>;
89
+ kind: typeof RecordKind;
90
+ type: 'object';
91
+ patternProperties: {
92
+ [pattern: string]: T;
93
+ };
94
+ }
95
+ export interface TTuple<T extends TSchema[]> extends TSchema, CustomOptions {
96
+ 'typebox:output': StaticTuple<T>;
85
97
  kind: typeof TupleKind;
86
98
  type: 'array';
87
- items?: [...T];
99
+ items?: T;
88
100
  additionalItems?: false;
89
101
  minItems: number;
90
102
  maxItems: number;
91
- } & CustomOptions;
92
- export declare type TObject<T extends TProperties> = {
103
+ }
104
+ export interface TObject<T extends TProperties> extends TSchema, ObjectOptions {
105
+ 'typebox:output': StaticObject<T>;
93
106
  kind: typeof ObjectKind;
94
107
  type: 'object';
95
108
  properties: T;
96
109
  required?: string[];
97
- } & ObjectOptions;
98
- export declare type TUnion<T extends TSchema[]> = {
110
+ }
111
+ export interface TUnion<T extends TSchema[]> extends TSchema, CustomOptions {
112
+ 'typebox:output': StaticUnion<T>;
99
113
  kind: typeof UnionKind;
100
- anyOf: [...T];
101
- } & CustomOptions;
102
- export declare type TIntersect<T extends TSchema[]> = {
114
+ anyOf: T;
115
+ }
116
+ export interface TIntersect<T extends TSchema[]> extends TSchema, IntersectOptions {
117
+ 'typebox:output': StaticIntersect<T>;
103
118
  kind: typeof IntersectKind;
104
119
  type: 'object';
105
- allOf: [...T];
106
- } & IntersectOptions;
107
- export declare type TKeyOf<T extends TKey[]> = {
120
+ allOf: T;
121
+ }
122
+ export interface TKeyOf<T extends TKey[]> extends TSchema, CustomOptions {
123
+ 'typebox:output': StaticKeyOf<T>;
108
124
  kind: typeof KeyOfKind;
109
125
  type: 'string';
110
- enum: [...T];
111
- } & CustomOptions;
112
- export declare type TRecord<K extends TRecordKey, T extends TSchema> = {
113
- kind: typeof RecordKind;
114
- type: 'object';
115
- patternProperties: {
116
- [pattern: string]: T;
117
- };
118
- } & ObjectOptions;
119
- export declare type TArray<T extends TSchema> = {
126
+ enum: T;
127
+ }
128
+ export interface TArray<T extends TSchema> extends TSchema, ArrayOptions {
129
+ 'typebox:output': StaticArray<T>;
120
130
  kind: typeof ArrayKind;
121
131
  type: 'array';
122
132
  items: T;
123
- } & ArrayOptions;
124
- export declare type TLiteral<T extends TValue> = {
133
+ }
134
+ export interface TLiteral<T extends TValue> extends TSchema, CustomOptions {
135
+ 'typebox:output': StaticLiteral<T>;
125
136
  kind: typeof LiteralKind;
126
137
  const: T;
127
- } & CustomOptions;
128
- export declare type TEnum<T extends TEnumKey[]> = {
138
+ }
139
+ export interface TEnum<T extends TEnumKey[]> extends TSchema, CustomOptions {
140
+ 'typebox:output': StaticEnum<T>;
129
141
  kind: typeof EnumKind;
130
142
  anyOf: T;
131
- } & CustomOptions;
132
- export declare type TString = {
143
+ }
144
+ export interface TString extends TSchema, StringOptions<string> {
145
+ 'typebox:output': string;
133
146
  kind: typeof StringKind;
134
147
  type: 'string';
135
- } & StringOptions<string>;
136
- export declare type TNumber = {
148
+ }
149
+ export interface TNumber extends TSchema, NumberOptions {
150
+ 'typebox:output': number;
137
151
  kind: typeof NumberKind;
138
152
  type: 'number';
139
- } & NumberOptions;
140
- export declare type TInteger = {
153
+ }
154
+ export interface TInteger extends TSchema, NumberOptions {
155
+ 'typebox:output': number;
141
156
  kind: typeof IntegerKind;
142
157
  type: 'integer';
143
- } & NumberOptions;
144
- export declare type TBoolean = {
158
+ }
159
+ export interface TBoolean extends TSchema, CustomOptions {
160
+ 'typebox:output': boolean;
145
161
  kind: typeof BooleanKind;
146
162
  type: 'boolean';
147
- } & CustomOptions;
148
- export declare type TNull = {
163
+ }
164
+ export interface TNull extends TSchema, CustomOptions {
165
+ 'typebox:output': null;
149
166
  kind: typeof NullKind;
150
167
  type: 'null';
151
- } & CustomOptions;
152
- export declare type TUnknown = {
168
+ }
169
+ export interface TUnknown extends TSchema, CustomOptions {
170
+ 'typebox:output': unknown;
153
171
  kind: typeof UnknownKind;
154
- } & CustomOptions;
155
- export declare type TAny = {
172
+ }
173
+ export interface TAny extends TSchema, CustomOptions {
174
+ 'typebox:output': any;
156
175
  kind: typeof AnyKind;
157
- } & CustomOptions;
176
+ }
158
177
  export declare const ConstructorKind: unique symbol;
159
178
  export declare const FunctionKind: unique symbol;
160
179
  export declare const PromiseKind: unique symbol;
161
180
  export declare const UndefinedKind: unique symbol;
162
181
  export declare const VoidKind: unique symbol;
163
- export declare type TConstructor<T extends TSchema[], U extends TSchema> = {
182
+ export interface TConstructor<T extends TSchema[], U extends TSchema> extends TSchema, CustomOptions {
183
+ 'typebox:output': StaticConstructor<T, U>;
164
184
  kind: typeof ConstructorKind;
165
185
  type: 'constructor';
166
- arguments: readonly [...T];
167
- returns: U;
168
- } & CustomOptions;
169
- export declare type TFunction<T extends TSchema[], U extends TSchema> = {
186
+ arguments: TSchema[];
187
+ returns: TSchema;
188
+ }
189
+ export interface TFunction<T extends TSchema[], U extends TSchema> extends TSchema, CustomOptions {
190
+ 'typebox:output': StaticFunction<T, U>;
170
191
  kind: typeof FunctionKind;
171
192
  type: 'function';
172
- arguments: readonly [...T];
173
- returns: U;
174
- } & CustomOptions;
175
- export declare type TPromise<T extends TSchema> = {
193
+ arguments: TSchema[];
194
+ returns: TSchema;
195
+ }
196
+ export interface TPromise<T extends TSchema> extends TSchema, CustomOptions {
197
+ 'typebox:output': StaticPromise<T>;
176
198
  kind: typeof PromiseKind;
177
199
  type: 'promise';
178
- item: T;
179
- } & CustomOptions;
180
- export declare type TUndefined = {
200
+ item: TSchema;
201
+ }
202
+ export interface TUndefined extends TSchema, CustomOptions {
203
+ 'typebox:output': undefined;
181
204
  kind: typeof UndefinedKind;
182
205
  type: 'undefined';
183
- } & CustomOptions;
184
- export declare type TVoid = {
206
+ }
207
+ export interface TVoid extends TSchema, CustomOptions {
208
+ 'typebox:output': void;
185
209
  kind: typeof VoidKind;
186
210
  type: 'void';
187
- } & CustomOptions;
188
- export declare type TSchema = TIntersect<any> | TUnion<any> | TTuple<any> | TObject<any> | TKeyOf<any> | TRecord<any, any> | TArray<any> | TEnum<any> | TLiteral<any> | TString | TNumber | TInteger | TBoolean | TNull | TUnknown | TAny | TConstructor<any[], any> | TFunction<any[], any> | TPromise<any> | TUndefined | TVoid;
189
- export declare type TRequired<T extends TProperties> = {
190
- [K in keyof T]: T[K] extends TReadonlyOptional<infer U> ? TReadonly<U> : T[K] extends TReadonly<infer U> ? TReadonly<U> : T[K] extends TOptional<infer U> ? U : T[K];
191
- };
192
- export declare type TPartial<T extends TProperties> = {
193
- [K in keyof T]: T[K] extends TReadonlyOptional<infer U> ? TReadonlyOptional<U> : T[K] extends TReadonly<infer U> ? TReadonlyOptional<U> : T[K] extends TOptional<infer U> ? TOptional<U> : TOptional<T[K]>;
194
- };
211
+ }
195
212
  export declare type UnionToIntersect<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
196
- export declare type ObjectPropertyKeys<T> = T extends TObject<infer U> ? PropertyKeys<U> : never;
197
- export declare type PropertyKeys<T extends TProperties> = keyof T;
198
- export declare type ReadonlyOptionalPropertyKeys<T extends TProperties> = {
213
+ export declare type StaticReadonlyOptionalPropertyKeys<T extends TProperties> = {
199
214
  [K in keyof T]: T[K] extends TReadonlyOptional<TSchema> ? K : never;
200
215
  }[keyof T];
201
- export declare type ReadonlyPropertyKeys<T extends TProperties> = {
216
+ export declare type StaticReadonlyPropertyKeys<T extends TProperties> = {
202
217
  [K in keyof T]: T[K] extends TReadonly<TSchema> ? K : never;
203
218
  }[keyof T];
204
- export declare type OptionalPropertyKeys<T extends TProperties> = {
219
+ export declare type StaticOptionalPropertyKeys<T extends TProperties> = {
205
220
  [K in keyof T]: T[K] extends TOptional<TSchema> ? K : never;
206
221
  }[keyof T];
207
- export declare type RequiredPropertyKeys<T extends TProperties> = keyof Omit<T, ReadonlyOptionalPropertyKeys<T> | ReadonlyPropertyKeys<T> | OptionalPropertyKeys<T>>;
208
- export declare type ReduceModifiers<T extends object> = {
209
- [K in keyof T]: T[K];
222
+ export declare type StaticRequiredPropertyKeys<T extends TProperties> = keyof Omit<T, StaticReadonlyOptionalPropertyKeys<T> | StaticReadonlyPropertyKeys<T> | StaticOptionalPropertyKeys<T>>;
223
+ export declare type StaticIntersectEvaluate<T extends readonly TSchema[]> = {
224
+ [K in keyof T]: Static<T[K]>;
225
+ };
226
+ export declare type StaticIntersectReduce<I extends unknown, T extends readonly any[]> = T extends [infer A, ...infer B] ? StaticIntersectReduce<I & A, B> : I;
227
+ export declare type StaticRequired<T extends TProperties> = {
228
+ [K in keyof T]: T[K] extends TReadonlyOptional<infer U> ? TReadonly<U> : T[K] extends TReadonly<infer U> ? TReadonly<U> : T[K] extends TOptional<infer U> ? U : T[K];
210
229
  };
211
- export declare type StaticModifiers<T extends TProperties> = {
212
- readonly [K in ReadonlyOptionalPropertyKeys<T>]?: T[K] extends TReadonlyOptional<infer U> ? Static<U> : never;
230
+ export declare type StaticPartial<T extends TProperties> = {
231
+ [K in keyof T]: T[K] extends TReadonlyOptional<infer U> ? TReadonlyOptional<U> : T[K] extends TReadonly<infer U> ? TReadonlyOptional<U> : T[K] extends TOptional<infer U> ? TOptional<U> : TOptional<T[K]>;
232
+ };
233
+ export declare type StaticProperties<T extends TProperties> = {
234
+ readonly [K in StaticReadonlyOptionalPropertyKeys<T>]?: Static<T[K]>;
213
235
  } & {
214
- readonly [K in ReadonlyPropertyKeys<T>]: T[K] extends TReadonly<infer U> ? Static<U> : never;
236
+ readonly [K in StaticReadonlyPropertyKeys<T>]: Static<T[K]>;
215
237
  } & {
216
- [K in OptionalPropertyKeys<T>]?: T[K] extends TOptional<infer U> ? Static<U> : never;
238
+ [K in StaticOptionalPropertyKeys<T>]?: Static<T[K]>;
217
239
  } & {
218
- [K in RequiredPropertyKeys<T>]: Static<T[K]>;
240
+ [K in StaticRequiredPropertyKeys<T>]: Static<T[K]>;
219
241
  };
242
+ export declare type StaticRecord<K extends TRecordKey, T extends TSchema> = K extends TString ? Record<string, Static<T>> : K extends TNumber ? Record<number, Static<T>> : K extends TKeyOf<TKey[]> ? Record<K['typebox:output'], Static<T>> : K extends TUnion<TSchema[]> ? Record<K['typebox:output'], Static<T>> : never;
220
243
  export declare type StaticEnum<T> = T extends TEnumKey<infer U>[] ? U : never;
221
244
  export declare type StaticKeyOf<T extends TKey[]> = T extends Array<infer K> ? K : never;
222
- export declare type StaticIntersect<T extends readonly TSchema[]> = UnionToIntersect<StaticUnion<T>>;
245
+ export declare type StaticIntersect<T extends readonly TSchema[]> = StaticIntersectReduce<unknown, StaticIntersectEvaluate<T>>;
223
246
  export declare type StaticUnion<T extends readonly TSchema[]> = {
224
247
  [K in keyof T]: Static<T[K]>;
225
248
  }[number];
226
249
  export declare type StaticTuple<T extends readonly TSchema[]> = {
227
250
  [K in keyof T]: Static<T[K]>;
228
251
  };
229
- export declare type StaticObject<T extends TProperties> = ReduceModifiers<StaticModifiers<T>>;
230
- export declare type StaticRecord<K extends TRecordKey, T extends TSchema> = K extends TString ? {
231
- [key: string]: Static<T>;
232
- } : K extends TNumber ? {
233
- [key: number]: Static<T>;
234
- } : K extends TUnion<infer L> ? L extends TLiteral<any>[] ? {
235
- [K in StaticUnion<L>]: Static<T>;
236
- } : never : never;
252
+ export declare type StaticObject<T extends TProperties> = StaticProperties<T> extends infer I ? {
253
+ [K in keyof I]: I[K];
254
+ } : never;
237
255
  export declare type StaticArray<T extends TSchema> = Array<Static<T>>;
238
256
  export declare type StaticLiteral<T extends TValue> = T;
239
- export declare type StaticConstructor<T extends readonly TSchema[], U extends TSchema> = new (...args: unknown[]) => Static<U>;
240
- export declare type StaticFunction<T extends readonly TSchema[], U extends TSchema> = (...args: unknown[]) => Static<U>;
257
+ export declare type StaticParameters<T extends readonly TSchema[]> = {
258
+ [K in keyof T]: Static<T[K]>;
259
+ };
260
+ export declare type StaticConstructor<T extends readonly TSchema[], U extends TSchema> = new (...args: [...StaticParameters<T>]) => Static<U>;
261
+ export declare type StaticFunction<T extends readonly TSchema[], U extends TSchema> = (...args: [...StaticParameters<T>]) => Static<U>;
241
262
  export declare type StaticPromise<T extends TSchema> = Promise<Static<T>>;
242
- export declare type Static<T> = T extends TKeyOf<infer U> ? StaticKeyOf<U> : T extends TIntersect<infer U> ? StaticIntersect<U> : T extends TUnion<infer U> ? StaticUnion<U> : T extends TTuple<infer U> ? StaticTuple<U> : T extends TObject<infer U> ? StaticObject<U> : T extends TRecord<infer K, infer U> ? StaticRecord<K, U> : T extends TArray<infer U> ? StaticArray<U> : T extends TEnum<infer U> ? StaticEnum<U> : T extends TLiteral<infer U> ? StaticLiteral<U> : T extends TString ? string : T extends TNumber ? number : T extends TInteger ? number : T extends TBoolean ? boolean : T extends TNull ? null : T extends TUnknown ? unknown : T extends TAny ? any : T extends TConstructor<infer U, infer R> ? StaticConstructor<U, R> : T extends TFunction<infer U, infer R> ? StaticFunction<U, R> : T extends TPromise<infer U> ? StaticPromise<U> : T extends TUndefined ? undefined : T extends TVoid ? void : never;
263
+ export declare type Static<T> = T extends TSchema ? T['typebox:output'] : never;
243
264
  export declare class TypeBuilder {
244
- /** `STANDARD` Modifies a schema object property to be `readonly` and `optional`. */
265
+ /** `Standard` Modifies an object property to be both readonly and optional */
245
266
  ReadonlyOptional<T extends TSchema>(item: T): TReadonlyOptional<T>;
246
- /** `STANDARD` Modifies a schema object property to be `readonly`. */
267
+ /** `Standard` Modifies an object property to be readonly */
247
268
  Readonly<T extends TSchema>(item: T): TReadonly<T>;
248
- /** `STANDARD` Modifies a schema object property to be `optional`. */
269
+ /** `Standard` Modifies an object property to be optional */
249
270
  Optional<T extends TSchema>(item: T): TOptional<T>;
250
- /** `STANDARD` Creates a Tuple schema. */
271
+ /** `Standard` Creates a type type */
251
272
  Tuple<T extends TSchema[]>(items: [...T], options?: CustomOptions): TTuple<T>;
252
- /** `STANDARD` Creates a `object` schema with the given properties. */
273
+ /** `Standard` Creates an object type with the given properties */
253
274
  Object<T extends TProperties>(properties: T, options?: ObjectOptions): TObject<T>;
254
- /** `STANDARD` Creates an intersection schema. Note this function requires draft `2019-09` to constrain with `unevaluatedProperties`. */
275
+ /** `Standard` Creates an intersect type. */
255
276
  Intersect<T extends TSchema[]>(items: [...T], options?: IntersectOptions): TIntersect<T>;
256
- /** `STANDARD` Creates a Union schema. */
277
+ /** `Standard` Creates a union type */
257
278
  Union<T extends TSchema[]>(items: [...T], options?: CustomOptions): TUnion<T>;
258
- /** `STANDARD` Creates an `Array<T>` schema. */
279
+ /** `Standard` Creates an array type */
259
280
  Array<T extends TSchema>(items: T, options?: ArrayOptions): TArray<T>;
260
- /** `STANDARD` Creates an `Enum<T>` schema from a TypeScript `enum` definition. */
281
+ /** `Standard` Creates an enum type from a TypeScript enum */
261
282
  Enum<T extends TEnumType>(item: T, options?: CustomOptions): TEnum<TEnumKey<T[keyof T]>[]>;
262
- /** `STANDARD` Creates a literal schema. Supports `string | number | boolean` values. */
283
+ /** `Standard` Creates a literal type. Supports string, number and boolean values only */
263
284
  Literal<T extends TValue>(value: T, options?: CustomOptions): TLiteral<T>;
264
- /** `STANDARD` Creates a `string` schema. */
285
+ /** `Standard` Creates a string type */
265
286
  String<TCustomFormatOption extends string>(options?: StringOptions<StringFormatOption | TCustomFormatOption>): TString;
266
- /** `STANDARD` Creates a `string` schema from a regular expression. */
287
+ /** `Standard` Creates a string type from a regular expression */
267
288
  RegEx(regex: RegExp, options?: CustomOptions): TString;
268
- /** `STANDARD` Creates a `number` schema. */
289
+ /** `Standard` Creates a number type */
269
290
  Number(options?: NumberOptions): TNumber;
270
- /** `STANDARD` Creates a `integer` schema. */
291
+ /** `Standard` Creates an integer type */
271
292
  Integer(options?: NumberOptions): TInteger;
272
- /** `STANDARD` Creates a `boolean` schema. */
293
+ /** `Standard` Creates a boolean type */
273
294
  Boolean(options?: CustomOptions): TBoolean;
274
- /** `STANDARD` Creates a `null` schema. */
295
+ /** `Standard` Creates a null type */
275
296
  Null(options?: CustomOptions): TNull;
276
- /** `STANDARD` Creates an `unknown` schema. */
297
+ /** `Standard` Creates an unknown type */
277
298
  Unknown(options?: CustomOptions): TUnknown;
278
- /** `STANDARD` Creates an `any` schema. */
299
+ /** `Standard` Creates an any type */
279
300
  Any(options?: CustomOptions): TAny;
280
- /** `STANDARD` Creates a `keyof` schema. */
281
- KeyOf<T extends TObject<TProperties>>(schema: T, options?: CustomOptions): TKeyOf<ObjectPropertyKeys<T>[]>;
282
- /** `STANDARD` Creates a `Record<Keys, Value>` schema. */
301
+ /** `Standard` Creates a keyof type from the given object */
302
+ KeyOf<T extends TObject<TProperties>>(schema: T, options?: CustomOptions): TKeyOf<(keyof T['properties'])[]>;
303
+ /** `Standard` Creates a record type */
283
304
  Record<K extends TRecordKey, T extends TSchema>(key: K, value: T, options?: ObjectOptions): TRecord<K, T>;
284
- /** `STANDARD` Make all properties in schema object required. */
285
- Required<T extends TObject<TProperties>>(schema: T, options?: ObjectOptions): TObject<TRequired<T['properties']>>;
286
- /** `STANDARD` Make all properties in schema object optional. */
287
- Partial<T extends TObject<TProperties>>(schema: T, options?: ObjectOptions): TObject<TPartial<T['properties']>>;
288
- /** `STANDARD` Picks property keys from the given object schema. */
289
- Pick<T extends TObject<TProperties>, K extends PropertyKeys<T['properties']>[]>(schema: T, keys: [...K], options?: ObjectOptions): TObject<Pick<T['properties'], K[number]>>;
290
- /** `STANDARD` Omits property keys from the given object schema. */
291
- Omit<T extends TObject<TProperties>, K extends PropertyKeys<T['properties']>[]>(schema: T, keys: [...K], options?: ObjectOptions): TObject<Omit<T['properties'], K[number]>>;
292
- /** `STANDARD` Omits the `kind` and `modifier` properties from the given schema. */
305
+ /** `Standard` Makes all properties in the given object type required */
306
+ Required<T extends TObject<any>>(schema: T, options?: ObjectOptions): TObject<StaticRequired<T['properties']>>;
307
+ /** `Standard` Makes all properties in the given object type optional */
308
+ Partial<T extends TObject<any>>(schema: T, options?: ObjectOptions): TObject<StaticPartial<T['properties']>>;
309
+ /** `Standard` Picks property keys from the given object type */
310
+ Pick<T extends TObject<TProperties>, K extends (keyof T['properties'])[]>(schema: T, keys: [...K], options?: ObjectOptions): TObject<Pick<T['properties'], K[number]>>;
311
+ /** `Standard` Omits property keys from the given object type */
312
+ Omit<T extends TObject<any>, K extends (keyof T['properties'])[]>(schema: T, keys: [...K], options?: ObjectOptions): TObject<Omit<T['properties'], K[number]>>;
313
+ /** `Standard` Omits the `kind` and `modifier` properties from the underlying schema */
293
314
  Strict<T extends TSchema>(schema: T, options?: CustomOptions): T;
294
- /** `EXTENDED` Creates a `constructor` schema. */
315
+ /** `Extended` Creates a constructor type */
295
316
  Constructor<T extends TSchema[], U extends TSchema>(args: [...T], returns: U, options?: CustomOptions): TConstructor<T, U>;
296
- /** `EXTENDED` Creates a `function` schema. */
317
+ /** `Extended` Creates a function type */
297
318
  Function<T extends TSchema[], U extends TSchema>(args: [...T], returns: U, options?: CustomOptions): TFunction<T, U>;
298
- /** `EXTENDED` Creates a `Promise<T>` schema. */
319
+ /** `Extended` Creates a promise type */
299
320
  Promise<T extends TSchema>(item: T, options?: CustomOptions): TPromise<T>;
300
- /** `EXTENDED` Creates a `undefined` schema. */
321
+ /** `Extended` Creates a undefined type */
301
322
  Undefined(options?: CustomOptions): TUndefined;
302
- /** `EXTENDED` Creates a `void` schema. */
323
+ /** `Extended` Creates a void type */
303
324
  Void(options?: CustomOptions): TVoid;
304
- /** `EXPERIMENTAL` Creates a recursive type. */
325
+ /** `Experimental` Creates a recursive type */
305
326
  Rec<T extends TSchema>(callback: (self: TAny) => T, options?: CustomOptions): T;
306
- /** `EXPERIMENTAL` Creates a recursive type. Pending https://github.com/ajv-validator/ajv/issues/1709 */
307
- /** `EXPERIMENTAL` Creates a container for schema definitions. */
308
- Box<T extends TDefinitions>(definitions: T, options?: CustomOptions): TBox<T>;
309
- /** `EXPERIMENTAL` References a schema inside a box. The referenced box must specify an `$id`. */
310
- Ref<T extends TBox<TDefinitions>, K extends keyof T['definitions']>(box: T, key: K): T['definitions'][K];
311
- /** `EXPERIMENTAL` References a schema. The referenced schema must specify an `$id`. */
327
+ /** `Experimental` Creates a recursive type. Pending https://github.com/ajv-validator/ajv/issues/1709 */
328
+ /** `Experimental` Creates a namespace for a set of related types */
329
+ Namespace<T extends TDefinitions>($defs: T, options?: CustomOptions): TNamespace<T>;
330
+ /** `Experimental` References a type within a namespace. The referenced namespace must specify an `$id` */
331
+ Ref<T extends TNamespace<TDefinitions>, K extends keyof T['$defs']>(box: T, key: K): T['$defs'][K];
332
+ /** `Experimental` References type. The referenced type must specify an `$id` */
312
333
  Ref<T extends TSchema>(schema: T): T;
313
334
  }
314
335
  export declare const Type: TypeBuilder;
package/typebox.js CHANGED
@@ -28,15 +28,15 @@ THE SOFTWARE.
28
28
  ---------------------------------------------------------------------------*/
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
30
  exports.Type = exports.TypeBuilder = exports.VoidKind = exports.UndefinedKind = exports.PromiseKind = exports.FunctionKind = exports.ConstructorKind = exports.AnyKind = exports.UnknownKind = exports.NullKind = exports.BooleanKind = exports.IntegerKind = exports.NumberKind = exports.StringKind = exports.LiteralKind = exports.EnumKind = exports.ArrayKind = exports.RecordKind = exports.ObjectKind = exports.TupleKind = exports.UnionKind = exports.IntersectKind = exports.KeyOfKind = exports.BoxKind = exports.ReadonlyModifier = exports.OptionalModifier = exports.ReadonlyOptionalModifier = void 0;
31
- // ------------------------------------------------------------------------
31
+ // --------------------------------------------------------------------------
32
32
  // Modifiers
33
- // ------------------------------------------------------------------------
33
+ // --------------------------------------------------------------------------
34
34
  exports.ReadonlyOptionalModifier = Symbol('ReadonlyOptionalModifier');
35
35
  exports.OptionalModifier = Symbol('OptionalModifier');
36
36
  exports.ReadonlyModifier = Symbol('ReadonlyModifier');
37
- // ------------------------------------------------------------------------
37
+ // --------------------------------------------------------------------------
38
38
  // Schema Standard
39
- // ------------------------------------------------------------------------
39
+ // --------------------------------------------------------------------------
40
40
  exports.BoxKind = Symbol('BoxKind');
41
41
  exports.KeyOfKind = Symbol('KeyOfKind');
42
42
  exports.IntersectKind = Symbol('IntersectKind');
@@ -54,17 +54,17 @@ exports.BooleanKind = Symbol('BooleanKind');
54
54
  exports.NullKind = Symbol('NullKind');
55
55
  exports.UnknownKind = Symbol('UnknownKind');
56
56
  exports.AnyKind = Symbol('AnyKind');
57
- // ------------------------------------------------------------------------
58
- // Schema Extended
59
- // ------------------------------------------------------------------------
57
+ // --------------------------------------------------------------------------
58
+ // Extended Schema Types
59
+ // --------------------------------------------------------------------------
60
60
  exports.ConstructorKind = Symbol('ConstructorKind');
61
61
  exports.FunctionKind = Symbol('FunctionKind');
62
62
  exports.PromiseKind = Symbol('PromiseKind');
63
63
  exports.UndefinedKind = Symbol('UndefinedKind');
64
64
  exports.VoidKind = Symbol('VoidKind');
65
- // ------------------------------------------------------------------------
65
+ // --------------------------------------------------------------------------
66
66
  // Utility
67
- // ------------------------------------------------------------------------
67
+ // --------------------------------------------------------------------------
68
68
  function isObject(object) {
69
69
  return typeof object === 'object' && object !== null && !Array.isArray(object);
70
70
  }
@@ -78,32 +78,32 @@ function clone(object) {
78
78
  return object.map((item) => clone(item));
79
79
  return object;
80
80
  }
81
- // ------------------------------------------------------------------------
81
+ // --------------------------------------------------------------------------
82
82
  // TypeBuilder
83
- // ------------------------------------------------------------------------
83
+ // --------------------------------------------------------------------------
84
84
  class TypeBuilder {
85
- /** `STANDARD` Modifies a schema object property to be `readonly` and `optional`. */
85
+ /** `Standard` Modifies an object property to be both readonly and optional */
86
86
  ReadonlyOptional(item) {
87
87
  return { ...item, modifier: exports.ReadonlyOptionalModifier };
88
88
  }
89
- /** `STANDARD` Modifies a schema object property to be `readonly`. */
89
+ /** `Standard` Modifies an object property to be readonly */
90
90
  Readonly(item) {
91
91
  return { ...item, modifier: exports.ReadonlyModifier };
92
92
  }
93
- /** `STANDARD` Modifies a schema object property to be `optional`. */
93
+ /** `Standard` Modifies an object property to be optional */
94
94
  Optional(item) {
95
95
  return { ...item, modifier: exports.OptionalModifier };
96
96
  }
97
- /** `STANDARD` Creates a Tuple schema. */
97
+ /** `Standard` Creates a type type */
98
98
  Tuple(items, options = {}) {
99
99
  const additionalItems = false;
100
100
  const minItems = items.length;
101
101
  const maxItems = items.length;
102
- return (items.length > 0)
102
+ return ((items.length > 0)
103
103
  ? { ...options, kind: exports.TupleKind, type: 'array', items, additionalItems, minItems, maxItems }
104
- : { ...options, kind: exports.TupleKind, type: 'array', minItems, maxItems };
104
+ : { ...options, kind: exports.TupleKind, type: 'array', minItems, maxItems });
105
105
  }
106
- /** `STANDARD` Creates a `object` schema with the given properties. */
106
+ /** `Standard` Creates an object type with the given properties */
107
107
  Object(properties, options = {}) {
108
108
  const property_names = Object.keys(properties);
109
109
  const optional = property_names.filter(name => {
@@ -114,77 +114,83 @@ class TypeBuilder {
114
114
  });
115
115
  const required_names = property_names.filter(name => !optional.includes(name));
116
116
  const required = (required_names.length > 0) ? required_names : undefined;
117
- return (required) ?
118
- { ...options, kind: exports.ObjectKind, type: 'object', properties, required } :
119
- { ...options, kind: exports.ObjectKind, type: 'object', properties };
117
+ return ((required)
118
+ ? { ...options, kind: exports.ObjectKind, type: 'object', properties, required }
119
+ : { ...options, kind: exports.ObjectKind, type: 'object', properties });
120
120
  }
121
- /** `STANDARD` Creates an intersection schema. Note this function requires draft `2019-09` to constrain with `unevaluatedProperties`. */
121
+ /** `Standard` Creates an intersect type. */
122
122
  Intersect(items, options = {}) {
123
123
  return { ...options, kind: exports.IntersectKind, type: 'object', allOf: items };
124
124
  }
125
- /** `STANDARD` Creates a Union schema. */
125
+ /** `Standard` Creates a union type */
126
126
  Union(items, options = {}) {
127
127
  return { ...options, kind: exports.UnionKind, anyOf: items };
128
128
  }
129
- /** `STANDARD` Creates an `Array<T>` schema. */
129
+ /** `Standard` Creates an array type */
130
130
  Array(items, options = {}) {
131
131
  return { ...options, kind: exports.ArrayKind, type: 'array', items };
132
132
  }
133
- /** `STANDARD` Creates an `Enum<T>` schema from a TypeScript `enum` definition. */
133
+ /** `Standard` Creates an enum type from a TypeScript enum */
134
134
  Enum(item, options = {}) {
135
135
  const values = Object.keys(item).filter(key => isNaN(key)).map(key => item[key]);
136
136
  const anyOf = values.map(value => typeof value === 'string' ? { type: 'string', const: value } : { type: 'number', const: value });
137
137
  return { ...options, kind: exports.EnumKind, anyOf };
138
138
  }
139
- /** `STANDARD` Creates a literal schema. Supports `string | number | boolean` values. */
139
+ /** `Standard` Creates a literal type. Supports string, number and boolean values only */
140
140
  Literal(value, options = {}) {
141
141
  return { ...options, kind: exports.LiteralKind, const: value, type: typeof value };
142
142
  }
143
- /** `STANDARD` Creates a `string` schema. */
143
+ /** `Standard` Creates a string type */
144
144
  String(options = {}) {
145
145
  return { ...options, kind: exports.StringKind, type: 'string' };
146
146
  }
147
- /** `STANDARD` Creates a `string` schema from a regular expression. */
147
+ /** `Standard` Creates a string type from a regular expression */
148
148
  RegEx(regex, options = {}) {
149
149
  return this.String({ ...options, pattern: regex.source });
150
150
  }
151
- /** `STANDARD` Creates a `number` schema. */
151
+ /** `Standard` Creates a number type */
152
152
  Number(options = {}) {
153
153
  return { ...options, kind: exports.NumberKind, type: 'number' };
154
154
  }
155
- /** `STANDARD` Creates a `integer` schema. */
155
+ /** `Standard` Creates an integer type */
156
156
  Integer(options = {}) {
157
157
  return { ...options, kind: exports.IntegerKind, type: 'integer' };
158
158
  }
159
- /** `STANDARD` Creates a `boolean` schema. */
159
+ /** `Standard` Creates a boolean type */
160
160
  Boolean(options = {}) {
161
161
  return { ...options, kind: exports.BooleanKind, type: 'boolean' };
162
162
  }
163
- /** `STANDARD` Creates a `null` schema. */
163
+ /** `Standard` Creates a null type */
164
164
  Null(options = {}) {
165
165
  return { ...options, kind: exports.NullKind, type: 'null' };
166
166
  }
167
- /** `STANDARD` Creates an `unknown` schema. */
167
+ /** `Standard` Creates an unknown type */
168
168
  Unknown(options = {}) {
169
169
  return { ...options, kind: exports.UnknownKind };
170
170
  }
171
- /** `STANDARD` Creates an `any` schema. */
171
+ /** `Standard` Creates an any type */
172
172
  Any(options = {}) {
173
173
  return { ...options, kind: exports.AnyKind };
174
174
  }
175
- /** `STANDARD` Creates a `keyof` schema. */
175
+ /** `Standard` Creates a keyof type from the given object */
176
176
  KeyOf(schema, options = {}) {
177
177
  const keys = Object.keys(schema.properties);
178
178
  return { ...options, kind: exports.KeyOfKind, type: 'string', enum: keys };
179
179
  }
180
- /** `STANDARD` Creates a `Record<Keys, Value>` schema. */
180
+ /** `Standard` Creates a record type */
181
181
  Record(key, value, options = {}) {
182
- const pattern = key.kind === exports.UnionKind ? `^${key.anyOf.map((literal) => literal.const).join('|')}$` :
183
- key.kind === exports.NumberKind ? '^(0|[1-9][0-9]*)$' :
184
- key.pattern ? key.pattern : '^.*$';
182
+ const pattern = (() => {
183
+ switch (key.kind) {
184
+ case exports.UnionKind: return `^${key.anyOf.map((literal) => literal.const).join('|')}$`;
185
+ case exports.KeyOfKind: return `^${key.enum.join('|')}$`;
186
+ case exports.NumberKind: return '^(0|[1-9][0-9]*)$';
187
+ case exports.StringKind: return key.pattern ? key.pattern : '^.*$';
188
+ default: throw Error('Invalid Record Key');
189
+ }
190
+ })();
185
191
  return { ...options, kind: exports.RecordKind, type: 'object', patternProperties: { [pattern]: value } };
186
192
  }
187
- /** `STANDARD` Make all properties in schema object required. */
193
+ /** `Standard` Makes all properties in the given object type required */
188
194
  Required(schema, options = {}) {
189
195
  const next = { ...clone(schema), ...options };
190
196
  next.required = Object.keys(next.properties);
@@ -207,7 +213,7 @@ class TypeBuilder {
207
213
  }
208
214
  return next;
209
215
  }
210
- /** `STANDARD` Make all properties in schema object optional. */
216
+ /** `Standard` Makes all properties in the given object type optional */
211
217
  Partial(schema, options = {}) {
212
218
  const next = { ...clone(schema), ...options };
213
219
  delete next.required;
@@ -230,7 +236,7 @@ class TypeBuilder {
230
236
  }
231
237
  return next;
232
238
  }
233
- /** `STANDARD` Picks property keys from the given object schema. */
239
+ /** `Standard` Picks property keys from the given object type */
234
240
  Pick(schema, keys, options = {}) {
235
241
  const next = { ...clone(schema), ...options };
236
242
  next.required = next.required ? next.required.filter((key) => keys.includes(key)) : undefined;
@@ -240,7 +246,7 @@ class TypeBuilder {
240
246
  }
241
247
  return next;
242
248
  }
243
- /** `STANDARD` Omits property keys from the given object schema. */
249
+ /** `Standard` Omits property keys from the given object type */
244
250
  Omit(schema, keys, options = {}) {
245
251
  const next = { ...clone(schema), ...options };
246
252
  next.required = next.required ? next.required.filter((key) => !keys.includes(key)) : undefined;
@@ -250,50 +256,49 @@ class TypeBuilder {
250
256
  }
251
257
  return next;
252
258
  }
253
- /** `STANDARD` Omits the `kind` and `modifier` properties from the given schema. */
259
+ /** `Standard` Omits the `kind` and `modifier` properties from the underlying schema */
254
260
  Strict(schema, options = {}) {
255
261
  return JSON.parse(JSON.stringify({ ...options, ...schema }));
256
262
  }
257
- /** `EXTENDED` Creates a `constructor` schema. */
263
+ /** `Extended` Creates a constructor type */
258
264
  Constructor(args, returns, options = {}) {
259
265
  return { ...options, kind: exports.ConstructorKind, type: 'constructor', arguments: args, returns };
260
266
  }
261
- /** `EXTENDED` Creates a `function` schema. */
267
+ /** `Extended` Creates a function type */
262
268
  Function(args, returns, options = {}) {
263
269
  return { ...options, kind: exports.FunctionKind, type: 'function', arguments: args, returns };
264
270
  }
265
- /** `EXTENDED` Creates a `Promise<T>` schema. */
271
+ /** `Extended` Creates a promise type */
266
272
  Promise(item, options = {}) {
267
273
  return { ...options, type: 'promise', kind: exports.PromiseKind, item };
268
274
  }
269
- /** `EXTENDED` Creates a `undefined` schema. */
275
+ /** `Extended` Creates a undefined type */
270
276
  Undefined(options = {}) {
271
277
  return { ...options, type: 'undefined', kind: exports.UndefinedKind };
272
278
  }
273
- /** `EXTENDED` Creates a `void` schema. */
279
+ /** `Extended` Creates a void type */
274
280
  Void(options = {}) {
275
281
  return { ...options, type: 'void', kind: exports.VoidKind };
276
282
  }
277
- /** `EXPERIMENTAL` Creates a recursive type. */
283
+ /** `Experimental` Creates a recursive type */
278
284
  Rec(callback, options = {}) {
279
285
  const $id = options.$id || '';
280
- const self = callback({ $ref: `${$id}#/definitions/self` });
281
- return { ...options, $ref: `${$id}#/definitions/self`, definitions: { self } };
286
+ const self = callback({ $ref: `${$id}#/$defs/self` });
287
+ return { ...options, $ref: `${$id}#/$defs/self`, $defs: { self } };
282
288
  }
283
- /** `EXPERIMENTAL` Creates a recursive type. Pending https://github.com/ajv-validator/ajv/issues/1709 */
289
+ /** `Experimental` Creates a recursive type. Pending https://github.com/ajv-validator/ajv/issues/1709 */
284
290
  // public Rec<T extends TProperties>($id: string, callback: (self: TAny) => T, options: ObjectOptions = {}): TObject<T> {
285
291
  // const properties = callback({ $recursiveRef: `${$id}` } as any)
286
292
  // return { ...options, kind: ObjectKind, $id, $recursiveAnchor: true, type: 'object', properties }
287
293
  // }
288
- /** `EXPERIMENTAL` Creates a container for schema definitions. */
289
- Box(definitions, options = {}) {
290
- return { ...options, kind: exports.BoxKind, definitions };
294
+ /** `Experimental` Creates a namespace for a set of related types */
295
+ Namespace($defs, options = {}) {
296
+ return { ...options, kind: exports.BoxKind, $defs };
291
297
  }
292
- /** `EXPERIMENTAL` References a schema. */
293
298
  Ref(...args) {
294
299
  const $id = args[0]['$id'] || '';
295
300
  const key = args[1];
296
- return (args.length === 2) ? { $ref: `${$id}#/definitions/${key}` } : { $ref: $id };
301
+ return (args.length === 2) ? { $ref: `${$id}#/$defs/${key}` } : { $ref: $id };
297
302
  }
298
303
  }
299
304
  exports.TypeBuilder = TypeBuilder;