@sinclair/typebox 0.20.4 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/package.json +4 -4
  2. package/readme.md +55 -13
  3. package/typebox.d.ts +109 -121
  4. package/typebox.js +44 -39
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinclair/typebox",
3
- "version": "0.20.4",
3
+ "version": "0.21.1",
4
4
  "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
5
5
  "keywords": [
6
6
  "json-schema",
@@ -23,14 +23,14 @@
23
23
  "test": "hammer task spec"
24
24
  },
25
25
  "devDependencies": {
26
- "@sinclair/hammer": "^0.12.1",
26
+ "@sinclair/hammer": "^0.15.7",
27
27
  "@types/chai": "^4.2.16",
28
28
  "@types/mocha": "^8.2.2",
29
29
  "@types/node": "^14.14.37",
30
30
  "ajv": "^8.6.2",
31
31
  "ajv-formats": "^2.0.2",
32
32
  "chai": "^4.3.4",
33
- "mocha": "^8.3.2",
34
- "typescript": "^4.3.5"
33
+ "mocha": "^9.1.2",
34
+ "typescript": "^4.5.2"
35
35
  }
36
36
  }
package/readme.md CHANGED
@@ -38,7 +38,7 @@ type T = Static<typeof T> // type T = string
38
38
 
39
39
  ## Overview
40
40
 
41
- TypeBox is a library that creates in-memory JSON Schema objects that can be statically resolved to TypeScript types. The schemas produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox allows one to create a unified type that can be statically checked by the TypeScript compiler and runtime asserted using standard JSON Schema validation.
41
+ TypeBox is a library that builds in-memory JSON Schema objects that can be statically resolved to TypeScript types. The schemas produced by this library are designed to match the static type checking rules of the TypeScript compiler. TypeBox allows one to create a unified type that can be statically checked by the TypeScript compiler and runtime asserted using standard JSON Schema validation.
42
42
 
43
43
  TypeBox can be used as a simple tool to build up complex schemas or integrated into RPC or REST services to help validate JSON data received over the wire. TypeBox does not provide any JSON schema validation. Please use libraries such as AJV to validate schemas built with this library.
44
44
 
@@ -59,6 +59,7 @@ License MIT
59
59
  - [Extended Types](#Extended-Types)
60
60
  - [Strict](#Strict)
61
61
  - [Validation](#Validation)
62
+ - [OpenAPI](#OpenAPI)
62
63
 
63
64
  <a name="Example"></a>
64
65
 
@@ -307,7 +308,7 @@ The following table outlines the TypeBox mappings between TypeScript and JSON sc
307
308
  │ Type.Number() │ │ y: { │
308
309
  │ ) │ │ type: 'number' │
309
310
  │ }) │ │ } │
310
- │ ) │ │ }
311
+ │ ) │ │ },
311
312
  │ │ │ required: ['x', 'y'] │
312
313
  │ │ │ } │
313
314
  │ │ │ │
@@ -446,10 +447,10 @@ const R = Type.Ref(T) // const R = {
446
447
  // }
447
448
  ```
448
449
 
449
- 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.
450
451
 
451
452
  ```typescript
452
- const Math3D = Type.Box({ // const Math3D = {
453
+ const Math3D = Type.Namespace({ // const Math3D = {
453
454
  Vector4: Type.Object({ // $id: 'Math3D',
454
455
  x: Type.Number(), // definitions: {
455
456
  y: Type.Number(), // Vector4: {
@@ -690,30 +691,30 @@ const ok = ajv.validate(User, {
690
691
 
691
692
  #### Reference Types
692
693
 
693
- 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.
694
695
 
695
696
  ```typescript
696
697
  //--------------------------------------------------------------------------------------------
697
698
  //
698
- // Common Types
699
+ // Shared Types
699
700
  //
700
701
  //--------------------------------------------------------------------------------------------
701
702
 
702
- const Common = Type.Box({
703
+ const Shared = Type.Namespace({
703
704
  UserId: Type.String({ format: 'uuid' }),
704
705
  Email: Type.String({ format: 'email' })
705
- }, { $id: 'Common' })
706
+ }, { $id: 'Shared' })
706
707
 
707
708
  //--------------------------------------------------------------------------------------------
708
709
  //
709
- // Setup AJV validator with the following options and formats
710
+ // Setup Validator and Register Shared Types
710
711
  //
711
712
  //--------------------------------------------------------------------------------------------
712
713
 
713
714
  const ajv = addFormats(new Ajv({}), [...])
714
715
  .addKeyword('kind')
715
716
  .addKeyword('modifier')
716
- .addSchema(Common) // <-- Register Common Types
717
+ .addSchema(Shared) // <-- Register Shared Types
717
718
 
718
719
  //--------------------------------------------------------------------------------------------
719
720
  //
@@ -722,8 +723,8 @@ const ajv = addFormats(new Ajv({}), [...])
722
723
  //--------------------------------------------------------------------------------------------
723
724
 
724
725
  const User = Type.Object({
725
- userId: Type.Ref(Common, 'UserId'),
726
- email: Type.Ref(Common, 'Email'),
726
+ userId: Type.Ref(Shared, 'UserId'),
727
+ email: Type.Ref(Shared, 'Email'),
727
728
  online: Type.Boolean()
728
729
  }, { additionalProperties: false })
729
730
 
@@ -741,4 +742,45 @@ const ok = ajv.validate(User, {
741
742
 
742
743
  ```
743
744
 
744
- Please refer to the official AJV [documentation](https://ajv.js.org/guide/getting-started.html) for more information on using this validator.
745
+ Please refer to the official AJV [documentation](https://ajv.js.org/guide/getting-started.html) for additional information.
746
+
747
+ ### OpenAPI
748
+
749
+ TypeBox can be used to create schemas for OpenAPI, however users should be aware of the various differences between the JSON Schema and OpenAPI specifications. Two common instances where OpenAPI diverges from the JSON Schema specification is OpenAPI's handling of `string enum` and `nullable`. The following shows how you can use TypeBox to construct these types.
750
+
751
+ ```typescript
752
+ import { Type, Static, TNull, TLiteral, TUnion, TSchema } from '@sinclair/typebox'
753
+
754
+ //--------------------------------------------------------------------------------------------
755
+ //
756
+ // Nullable<T>
757
+ //
758
+ //--------------------------------------------------------------------------------------------
759
+
760
+ function Nullable<T extends TSchema>(schema: T): TUnion<[T, TNull]> {
761
+ return { ...schema, nullable: true } as any
762
+ }
763
+
764
+ const T = Nullable(Type.String()) // const T = {
765
+ // type: 'string',
766
+ // nullable: true
767
+ // }
768
+
769
+ type T = Static<typeof T> // type T = string | null
770
+
771
+ //--------------------------------------------------------------------------------------------
772
+ //
773
+ // StringUnion<[...]>
774
+ //
775
+ //--------------------------------------------------------------------------------------------
776
+
777
+ function StringUnion<T extends string[]>(values: [...T]): TUnion<{[K in keyof T]: T[K] }[number]> {
778
+ return { enum: values } as any
779
+ }
780
+
781
+ const T = StringUnion(['A', 'B', 'C']) // const T = {
782
+ // enum: ['A', 'B', 'C']
783
+ // }
784
+
785
+ type T = Static<typeof T> // type T = 'A' | 'B' | 'C'
786
+ ```
package/typebox.d.ts CHANGED
@@ -63,96 +63,99 @@ 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
+ definitions: T;
72
+ } & CustomOptions;
73
+ export declare type Infer<T> = {
74
+ '_infer': T;
75
+ };
66
76
  export declare type TEnumType = Record<string, string | number>;
67
77
  export declare type TKey = string | number;
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<string | number>;
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
84
  export declare type TProperties = {
78
85
  [key: string]: TSchema;
79
86
  };
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[]> = {
87
+ export declare type TTuple<I> = Infer<I> & {
85
88
  kind: typeof TupleKind;
86
89
  type: 'array';
87
- items?: [...T];
90
+ items?: TSchema[];
88
91
  additionalItems?: false;
89
92
  minItems: number;
90
93
  maxItems: number;
91
94
  } & CustomOptions;
92
- export declare type TObject<T extends TProperties> = {
95
+ export declare type TObject<I> = Infer<I> & {
93
96
  kind: typeof ObjectKind;
94
97
  type: 'object';
95
- properties: T;
98
+ properties: TProperties;
96
99
  required?: string[];
97
100
  } & ObjectOptions;
98
- export declare type TUnion<T extends TSchema[]> = {
101
+ export declare type TUnion<I> = Infer<I> & {
99
102
  kind: typeof UnionKind;
100
- anyOf: [...T];
103
+ anyOf: TSchema[];
101
104
  } & CustomOptions;
102
- export declare type TIntersect<T extends TSchema[]> = {
105
+ export declare type TIntersect<I> = Infer<I> & {
103
106
  kind: typeof IntersectKind;
104
107
  type: 'object';
105
- allOf: [...T];
108
+ allOf: TSchema[];
106
109
  } & IntersectOptions;
107
- export declare type TKeyOf<T extends TKey[]> = {
110
+ export declare type TKeyOf<I> = Infer<I> & {
108
111
  kind: typeof KeyOfKind;
109
112
  type: 'string';
110
- enum: [...T];
113
+ enum: string[];
111
114
  } & CustomOptions;
112
- export declare type TRecord<K extends TRecordKey, T extends TSchema> = {
115
+ export declare type TRecord<I> = Infer<I> & {
113
116
  kind: typeof RecordKind;
114
117
  type: 'object';
115
118
  patternProperties: {
116
- [pattern: string]: T;
119
+ [pattern: string]: TSchema;
117
120
  };
118
121
  } & ObjectOptions;
119
- export declare type TArray<T extends TSchema> = {
122
+ export declare type TArray<I> = Infer<I> & {
120
123
  kind: typeof ArrayKind;
121
124
  type: 'array';
122
- items: T;
125
+ items: any;
123
126
  } & ArrayOptions;
124
- export declare type TLiteral<T extends TValue> = {
127
+ export declare type TLiteral<I> = Infer<I> & {
125
128
  kind: typeof LiteralKind;
126
- const: T;
129
+ const: TValue;
127
130
  } & CustomOptions;
128
- export declare type TEnum<T extends TEnumKey[]> = {
131
+ export declare type TEnum<I> = Infer<I> & {
129
132
  kind: typeof EnumKind;
130
- anyOf: T;
133
+ anyOf: TSchema;
131
134
  } & CustomOptions;
132
- export declare type TString = {
135
+ export declare type TString = Infer<string> & {
133
136
  kind: typeof StringKind;
134
137
  type: 'string';
135
138
  } & StringOptions<string>;
136
- export declare type TNumber = {
139
+ export declare type TNumber = Infer<number> & {
137
140
  kind: typeof NumberKind;
138
141
  type: 'number';
139
142
  } & NumberOptions;
140
- export declare type TInteger = {
143
+ export declare type TInteger = Infer<number> & {
141
144
  kind: typeof IntegerKind;
142
145
  type: 'integer';
143
146
  } & NumberOptions;
144
- export declare type TBoolean = {
147
+ export declare type TBoolean = Infer<boolean> & {
145
148
  kind: typeof BooleanKind;
146
149
  type: 'boolean';
147
150
  } & CustomOptions;
148
- export declare type TNull = {
151
+ export declare type TNull = Infer<null> & {
149
152
  kind: typeof NullKind;
150
153
  type: 'null';
151
154
  } & CustomOptions;
152
- export declare type TUnknown = {
155
+ export declare type TUnknown = Infer<unknown> & {
153
156
  kind: typeof UnknownKind;
154
157
  } & CustomOptions;
155
- export declare type TAny = {
158
+ export declare type TAny = Infer<any> & {
156
159
  kind: typeof AnyKind;
157
160
  } & CustomOptions;
158
161
  export declare const ConstructorKind: unique symbol;
@@ -160,55 +163,44 @@ export declare const FunctionKind: unique symbol;
160
163
  export declare const PromiseKind: unique symbol;
161
164
  export declare const UndefinedKind: unique symbol;
162
165
  export declare const VoidKind: unique symbol;
163
- export declare type TConstructor<T extends TSchema[], U extends TSchema> = {
166
+ export declare type TConstructor<T> = Infer<T> & {
164
167
  kind: typeof ConstructorKind;
165
168
  type: 'constructor';
166
- arguments: readonly [...T];
167
- returns: U;
169
+ arguments: TSchema[];
170
+ returns: TSchema;
168
171
  } & CustomOptions;
169
- export declare type TFunction<T extends TSchema[], U extends TSchema> = {
172
+ export declare type TFunction<T> = Infer<T> & {
170
173
  kind: typeof FunctionKind;
171
174
  type: 'function';
172
- arguments: readonly [...T];
173
- returns: U;
175
+ arguments: TSchema[];
176
+ returns: TSchema;
174
177
  } & CustomOptions;
175
- export declare type TPromise<T extends TSchema> = {
178
+ export declare type TPromise<T> = Infer<T> & {
176
179
  kind: typeof PromiseKind;
177
180
  type: 'promise';
178
- item: T;
181
+ item: TSchema;
179
182
  } & CustomOptions;
180
- export declare type TUndefined = {
183
+ export declare type TUndefined = Infer<undefined> & {
181
184
  kind: typeof UndefinedKind;
182
185
  type: 'undefined';
183
186
  } & CustomOptions;
184
- export declare type TVoid = {
187
+ export declare type TVoid = Infer<void> & {
185
188
  kind: typeof VoidKind;
186
189
  type: 'void';
187
190
  } & 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
- };
191
+ export declare type TSchema = TIntersect<any> | TUnion<any> | TTuple<any> | TObject<any> | TKeyOf<any> | TRecord<any> | TArray<any> | TEnum<any> | TLiteral<any> | TString | TNumber | TInteger | TBoolean | TNull | TUnknown | TAny | TConstructor<any> | TFunction<any> | TPromise<any> | TUndefined | TVoid;
195
192
  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
193
  export declare type ReadonlyOptionalPropertyKeys<T extends TProperties> = {
199
- [K in keyof T]: T[K] extends TReadonlyOptional<infer U> ? K : never;
194
+ [K in keyof T]: T[K] extends TReadonlyOptional<TSchema> ? K : never;
200
195
  }[keyof T];
201
196
  export declare type ReadonlyPropertyKeys<T extends TProperties> = {
202
- [K in keyof T]: T[K] extends TReadonly<infer U> ? K : never;
197
+ [K in keyof T]: T[K] extends TReadonly<TSchema> ? K : never;
203
198
  }[keyof T];
204
199
  export declare type OptionalPropertyKeys<T extends TProperties> = {
205
- [K in keyof T]: T[K] extends TOptional<infer U> ? K : never;
200
+ [K in keyof T]: T[K] extends TOptional<TSchema> ? K : never;
206
201
  }[keyof T];
207
202
  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];
210
- };
211
- export declare type StaticModifiers<T extends TProperties> = {
203
+ export declare type StaticProperties<T extends TProperties> = {
212
204
  readonly [K in ReadonlyOptionalPropertyKeys<T>]?: Static<T[K]>;
213
205
  } & {
214
206
  readonly [K in ReadonlyPropertyKeys<T>]: Static<T[K]>;
@@ -226,14 +218,8 @@ export declare type StaticUnion<T extends readonly TSchema[]> = {
226
218
  export declare type StaticTuple<T extends readonly TSchema[]> = {
227
219
  [K in keyof T]: Static<T[K]>;
228
220
  };
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;
221
+ export declare type StaticObject<T extends TProperties> = StaticProperties<StaticProperties<T>>;
222
+ 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<any> ? Record<K['_infer'], Static<T>> : K extends TUnion<any> ? Record<K['_infer'], Static<T>> : never;
237
223
  export declare type StaticArray<T extends TSchema> = Array<Static<T>>;
238
224
  export declare type StaticLiteral<T extends TValue> = T;
239
225
  export declare type StaticConstructor<T extends readonly TSchema[], U extends TSchema> = new (...args: [...{
@@ -243,76 +229,78 @@ export declare type StaticFunction<T extends readonly TSchema[], U extends TSche
243
229
  [K in keyof T]: Static<T[K]>;
244
230
  }]) => Static<U>;
245
231
  export declare type StaticPromise<T extends TSchema> = Promise<Static<T>>;
246
- 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;
232
+ export declare type Static<T> = T extends TKeyOf<infer I> ? I : T extends TIntersect<infer I> ? I : T extends TUnion<infer I> ? I : T extends TTuple<infer I> ? I : T extends TObject<infer I> ? {
233
+ [K in keyof I]: I[K];
234
+ } : T extends TRecord<infer I> ? I : T extends TArray<infer I> ? I : T extends TEnum<infer I> ? I : T extends TLiteral<infer I> ? I : T extends TString ? T['_infer'] : T extends TNumber ? T['_infer'] : T extends TInteger ? T['_infer'] : T extends TBoolean ? T['_infer'] : T extends TNull ? T['_infer'] : T extends TUnknown ? T['_infer'] : T extends TAny ? T['_infer'] : T extends TConstructor<infer I> ? I : T extends TFunction<infer I> ? I : T extends TPromise<infer I> ? I : T extends TUndefined ? T['_infer'] : T extends TVoid ? T['_infer'] : never;
247
235
  export declare class TypeBuilder {
248
- /** `STANDARD` Modifies a schema object property to be `readonly` and `optional`. */
236
+ /** `standard` Modifies an object property to be both readonly and optional */
249
237
  ReadonlyOptional<T extends TSchema>(item: T): TReadonlyOptional<T>;
250
- /** `STANDARD` Modifies a schema object property to be `readonly`. */
238
+ /** `standard` Modifies an object property to be readonly */
251
239
  Readonly<T extends TSchema>(item: T): TReadonly<T>;
252
- /** `STANDARD` Modifies a schema object property to be `optional`. */
240
+ /** `standard` Modifies an object property to be optional */
253
241
  Optional<T extends TSchema>(item: T): TOptional<T>;
254
- /** `STANDARD` Creates a Tuple schema. */
255
- Tuple<T extends TSchema[]>(items: [...T], options?: CustomOptions): TTuple<T>;
256
- /** `STANDARD` Creates a `object` schema with the given properties. */
257
- Object<T extends TProperties>(properties: T, options?: ObjectOptions): TObject<T>;
258
- /** `STANDARD` Creates an intersection schema. Note this function requires draft `2019-09` to constrain with `unevaluatedProperties`. */
259
- Intersect<T extends TSchema[]>(items: [...T], options?: IntersectOptions): TIntersect<T>;
260
- /** `STANDARD` Creates a Union schema. */
261
- Union<T extends TSchema[]>(items: [...T], options?: CustomOptions): TUnion<T>;
262
- /** `STANDARD` Creates an `Array<T>` schema. */
263
- Array<T extends TSchema>(items: T, options?: ArrayOptions): TArray<T>;
264
- /** `STANDARD` Creates an `Enum<T>` schema from a TypeScript `enum` definition. */
265
- Enum<T extends TEnumType>(item: T, options?: CustomOptions): TEnum<TEnumKey<T[keyof T]>[]>;
266
- /** `STANDARD` Creates a literal schema. Supports `string | number | boolean` values. */
267
- Literal<T extends TValue>(value: T, options?: CustomOptions): TLiteral<T>;
268
- /** `STANDARD` Creates a `string` schema. */
242
+ /** `standard` Creates a type type */
243
+ Tuple<T extends TSchema[]>(items: [...T], options?: CustomOptions): TTuple<StaticTuple<T>>;
244
+ /** `standard` Creates an object type with the given properties */
245
+ Object<T extends TProperties>(properties: T, options?: ObjectOptions): TObject<StaticProperties<T>>;
246
+ /** `standard` Creates an intersection type. Note this function requires draft `2019-09` to constrain with `unevaluatedProperties` */
247
+ Intersect<T extends TSchema[]>(items: [...T], options?: IntersectOptions): TIntersect<StaticIntersect<T>>;
248
+ /** `standard` Creates a union type */
249
+ Union<T extends TSchema[]>(items: [...T], options?: CustomOptions): TUnion<StaticUnion<T>>;
250
+ /** `standard` Creates an array type */
251
+ Array<T extends TSchema>(items: T, options?: ArrayOptions): TArray<StaticArray<T>>;
252
+ /** `standard` Creates an enum type from a TypeScript enum */
253
+ Enum<T extends TEnumType>(item: T, options?: CustomOptions): TEnum<StaticEnum<TEnumKey<T[keyof T]>[]>>;
254
+ /** `standard` Creates a literal type. Supports string, number and boolean values only */
255
+ Literal<T extends TValue>(value: T, options?: CustomOptions): TLiteral<StaticLiteral<T>>;
256
+ /** `standard` Creates a string type */
269
257
  String<TCustomFormatOption extends string>(options?: StringOptions<StringFormatOption | TCustomFormatOption>): TString;
270
- /** `STANDARD` Creates a `string` schema from a regular expression. */
258
+ /** `standard` Creates a string type from a regular expression */
271
259
  RegEx(regex: RegExp, options?: CustomOptions): TString;
272
- /** `STANDARD` Creates a `number` schema. */
260
+ /** `standard` Creates a number type */
273
261
  Number(options?: NumberOptions): TNumber;
274
- /** `STANDARD` Creates a `integer` schema. */
262
+ /** `standard` Creates an integer type */
275
263
  Integer(options?: NumberOptions): TInteger;
276
- /** `STANDARD` Creates a `boolean` schema. */
264
+ /** `standard` Creates a boolean type */
277
265
  Boolean(options?: CustomOptions): TBoolean;
278
- /** `STANDARD` Creates a `null` schema. */
266
+ /** `standard` Creates a null type */
279
267
  Null(options?: CustomOptions): TNull;
280
- /** `STANDARD` Creates an `unknown` schema. */
268
+ /** `standard` Creates an unknown type */
281
269
  Unknown(options?: CustomOptions): TUnknown;
282
- /** `STANDARD` Creates an `any` schema. */
270
+ /** `standard` Creates an any type */
283
271
  Any(options?: CustomOptions): TAny;
284
- /** `STANDARD` Creates a `keyof` schema. */
285
- KeyOf<T extends TObject<TProperties>>(schema: T, options?: CustomOptions): TKeyOf<ObjectPropertyKeys<T>[]>;
286
- /** `STANDARD` Creates a `Record<Keys, Value>` schema. */
287
- Record<K extends TRecordKey, T extends TSchema>(key: K, value: T, options?: ObjectOptions): TRecord<K, T>;
288
- /** `STANDARD` Make all properties in schema object required. */
289
- Required<T extends TObject<TProperties>>(schema: T, options?: ObjectOptions): TObject<TRequired<T['properties']>>;
290
- /** `STANDARD` Make all properties in schema object optional. */
291
- Partial<T extends TObject<TProperties>>(schema: T, options?: ObjectOptions): TObject<TPartial<T['properties']>>;
292
- /** `STANDARD` Picks property keys from the given object schema. */
293
- Pick<T extends TObject<TProperties>, K extends PropertyKeys<T['properties']>[]>(schema: T, keys: [...K], options?: ObjectOptions): TObject<Pick<T['properties'], K[number]>>;
294
- /** `STANDARD` Omits property keys from the given object schema. */
295
- Omit<T extends TObject<TProperties>, K extends PropertyKeys<T['properties']>[]>(schema: T, keys: [...K], options?: ObjectOptions): TObject<Omit<T['properties'], K[number]>>;
296
- /** `STANDARD` Omits the `kind` and `modifier` properties from the given schema. */
272
+ /** `standard` Creates a keyof type from the given object */
273
+ KeyOf<T extends TObject<any>>(schema: T, options?: CustomOptions): TKeyOf<keyof T['_infer']>;
274
+ /** `standard` Creates a record type */
275
+ Record<K extends TRecordKey, T extends TSchema>(key: K, value: T, options?: ObjectOptions): TRecord<StaticRecord<K, T>>;
276
+ /** `standard` Makes all properties in the given object type required */
277
+ Required<T extends TObject<any>>(schema: T, options?: ObjectOptions): TObject<Required<T['_infer']>>;
278
+ /** `standard` Makes all properties in the given object type optional */
279
+ Partial<T extends TObject<any>>(schema: T, options?: ObjectOptions): TObject<Partial<T['_infer']>>;
280
+ /** `standard` Picks property keys from the given object type */
281
+ Pick<T extends TObject<any>, K extends (keyof T['_infer'])[]>(schema: T, keys: [...K], options?: ObjectOptions): TObject<Pick<T['_infer'], K[number]>>;
282
+ /** `standard` Omits property keys from the given object type */
283
+ Omit<T extends TObject<any>, K extends (keyof T['_infer'])[]>(schema: T, keys: [...K], options?: ObjectOptions): TObject<Omit<T['_infer'], K[number]>>;
284
+ /** `standard` Omits the `kind` and `modifier` properties from the underlying schema */
297
285
  Strict<T extends TSchema>(schema: T, options?: CustomOptions): T;
298
- /** `EXTENDED` Creates a `constructor` schema. */
299
- Constructor<T extends TSchema[], U extends TSchema>(args: [...T], returns: U, options?: CustomOptions): TConstructor<T, U>;
300
- /** `EXTENDED` Creates a `function` schema. */
301
- Function<T extends TSchema[], U extends TSchema>(args: [...T], returns: U, options?: CustomOptions): TFunction<T, U>;
302
- /** `EXTENDED` Creates a `Promise<T>` schema. */
303
- Promise<T extends TSchema>(item: T, options?: CustomOptions): TPromise<T>;
304
- /** `EXTENDED` Creates a `undefined` schema. */
286
+ /** `extended` Creates a constructor type */
287
+ Constructor<T extends TSchema[], U extends TSchema>(args: [...T], returns: U, options?: CustomOptions): TConstructor<StaticConstructor<T, U>>;
288
+ /** `extended` Creates a function type */
289
+ Function<T extends TSchema[], U extends TSchema>(args: [...T], returns: U, options?: CustomOptions): TFunction<StaticFunction<T, U>>;
290
+ /** `extended` Creates a promise type */
291
+ Promise<T extends TSchema>(item: T, options?: CustomOptions): TPromise<StaticPromise<T>>;
292
+ /** `extended` Creates a undefined type */
305
293
  Undefined(options?: CustomOptions): TUndefined;
306
- /** `EXTENDED` Creates a `void` schema. */
294
+ /** `extended` Creates a void type */
307
295
  Void(options?: CustomOptions): TVoid;
308
- /** `EXPERIMENTAL` Creates a recursive type. */
296
+ /** `experimental` Creates a recursive type */
309
297
  Rec<T extends TSchema>(callback: (self: TAny) => T, options?: CustomOptions): T;
310
- /** `EXPERIMENTAL` Creates a recursive type. Pending https://github.com/ajv-validator/ajv/issues/1709 */
311
- /** `EXPERIMENTAL` Creates a container for schema definitions. */
312
- Box<T extends TDefinitions>(definitions: T, options?: CustomOptions): TBox<T>;
313
- /** `EXPERIMENTAL` References a schema inside a box. The referenced box must specify an `$id`. */
314
- Ref<T extends TBox<TDefinitions>, K extends keyof T['definitions']>(box: T, key: K): T['definitions'][K];
315
- /** `EXPERIMENTAL` References a schema. The referenced schema must specify an `$id`. */
298
+ /** `experimental` Creates a recursive type. Pending https://github.com/ajv-validator/ajv/issues/1709 */
299
+ /** `experimental` Creates a namespace for a set of related types */
300
+ Namespace<T extends TDefinitions>(definitions: T, options?: CustomOptions): TNamespace<T>;
301
+ /** `experimental` References a type within a namespace. The referenced namespace must specify an `$id` */
302
+ Ref<T extends TNamespace<TDefinitions>, K extends keyof T['definitions']>(box: T, key: K): T['definitions'][K];
303
+ /** `experimental` References type. The referenced type must specify an `$id` */
316
304
  Ref<T extends TSchema>(schema: T): T;
317
305
  }
318
306
  export declare const Type: TypeBuilder;
package/typebox.js CHANGED
@@ -55,7 +55,7 @@ exports.NullKind = Symbol('NullKind');
55
55
  exports.UnknownKind = Symbol('UnknownKind');
56
56
  exports.AnyKind = Symbol('AnyKind');
57
57
  // ------------------------------------------------------------------------
58
- // Schema Extended
58
+ // Extended Schema Types
59
59
  // ------------------------------------------------------------------------
60
60
  exports.ConstructorKind = Symbol('ConstructorKind');
61
61
  exports.FunctionKind = Symbol('FunctionKind');
@@ -82,19 +82,19 @@ function clone(object) {
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;
@@ -103,7 +103,7 @@ class TypeBuilder {
103
103
  ? { ...options, kind: exports.TupleKind, type: 'array', items, additionalItems, minItems, maxItems }
104
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 => {
@@ -118,73 +118,79 @@ class TypeBuilder {
118
118
  { ...options, kind: exports.ObjectKind, type: 'object', properties, required } :
119
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 intersection type. Note this function requires draft `2019-09` to constrain with `unevaluatedProperties` */
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,46 +256,45 @@ 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
286
  const self = callback({ $ref: `${$id}#/definitions/self` });
281
287
  return { ...options, $ref: `${$id}#/definitions/self`, definitions: { 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 = {}) {
294
+ /** `experimental` Creates a namespace for a set of related types */
295
+ Namespace(definitions, options = {}) {
290
296
  return { ...options, kind: exports.BoxKind, definitions };
291
297
  }
292
- /** `EXPERIMENTAL` References a schema. */
293
298
  Ref(...args) {
294
299
  const $id = args[0]['$id'] || '';
295
300
  const key = args[1];