@sinclair/typebox 0.28.5 → 0.28.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sinclair/typebox",
3
- "version": "0.28.5",
3
+ "version": "0.28.6",
4
4
  "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
5
5
  "keywords": [
6
6
  "typescript",
package/readme.md CHANGED
@@ -11,6 +11,8 @@
11
11
 
12
12
  [![npm version](https://badge.fury.io/js/%40sinclair%2Ftypebox.svg)](https://badge.fury.io/js/%40sinclair%2Ftypebox)
13
13
  [![Downloads](https://img.shields.io/npm/dm/%40sinclair%2Ftypebox.svg)](https://www.npmjs.com/package/%40sinclair%2Ftypebox)
14
+ [![Install Size](https://packagephobia.com/badge?p=@sinclair/typebox)](https://packagephobia.com/result?p=@sinclair/typebox)
15
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
16
  [![GitHub CI](https://github.com/sinclairzx81/typebox/workflows/GitHub%20CI/badge.svg)](https://github.com/sinclairzx81/typebox/actions)
15
17
 
16
18
  </div>
@@ -1369,9 +1371,15 @@ const B = Value.Check(T, 'hello') // const B = true
1369
1371
 
1370
1372
  ### Policies
1371
1373
 
1372
- TypeBox validates using JSON Schema assertion policies by default. It is possible to override these policies and have TypeBox assert using TypeScript policies. The following overrides are available.
1374
+ TypeBox validates using standard JSON Schema assertion policies by default. It is possible to override some of these policies to have TypeBox assert inline with TypeScript static assertion rules. The following policy overrides are available.
1373
1375
 
1374
1376
  ```typescript
1377
+ // Disallow undefined values for optional properties (default is false)
1378
+ //
1379
+ // const A: { x?: number } = { x: undefined } - disallowed when enabled
1380
+
1381
+ TypeSystem.ExactOptionalPropertyTypes = true
1382
+
1375
1383
  // Allow arrays to validate as object types (default is false)
1376
1384
  //
1377
1385
  // const A: {} = [] - allowed in TS
package/typebox.d.ts CHANGED
@@ -14,6 +14,8 @@ export type TupleToUnion<T extends any[]> = {
14
14
  export type UnionToIntersect<U> = (U extends unknown ? (arg: U) => 0 : never) extends (arg: infer I) => 0 ? I : never;
15
15
  export type UnionLast<U> = UnionToIntersect<U extends unknown ? (x: U) => 0 : never> extends (x: infer L) => 0 ? L : never;
16
16
  export type UnionToTuple<U, L = UnionLast<U>> = [U] extends [never] ? [] : [...UnionToTuple<Exclude<U, L>>, L];
17
+ export type Discard<T extends unknown[], D extends unknown> = T extends [infer L, ...infer R] ? (L extends D ? Discard<R, D> : [L, ...Discard<R, D>]) : [];
18
+ export type Flat<T> = T extends [] ? [] : T extends [infer L] ? [...Flat<L>] : T extends [infer L, ...infer R] ? [...Flat<L>, ...Flat<R>] : [T];
17
19
  export type Assert<T, E> = T extends E ? T : never;
18
20
  export type Evaluate<T> = T extends infer O ? {
19
21
  [K in keyof O]: O[K];
@@ -168,27 +170,21 @@ export interface TFunction<T extends readonly TSchema[] = TSchema[], U extends T
168
170
  parameters: T;
169
171
  returns: U;
170
172
  }
171
- export type TIndexProperty<T extends TProperties, K extends Key> = T[K] extends infer R ? [R] : [
173
+ export type TIndexRest<T extends TSchema[], K extends Key> = T extends [infer L, ...infer R] ? [TIndexType<AssertType<L>, K>, ...TIndexRest<AssertRest<R>, K>] : [];
174
+ export type TIndexProperty<T extends TProperties, K extends Key> = K extends keyof T ? [T[K]] : [];
175
+ export type TIndexTuple<T extends TSchema[], K extends Key> = K extends keyof T ? [T[K]] : [];
176
+ export type TIndexType<T extends TSchema, K extends Key> = T extends TRecursive<infer S> ? TIndexType<S, K> : T extends TIntersect<infer S> ? IntersectType<AssertRest<Discard<Flat<TIndexRest<S, K>>, TNever>>> : T extends TUnion<infer S> ? UnionType<AssertRest<Flat<TIndexRest<S, K>>>> : T extends TObject<infer S> ? UnionType<AssertRest<Flat<TIndexProperty<S, K>>>> : T extends TTuple<infer S> ? UnionType<AssertRest<Flat<TIndexTuple<S, K>>>> : [
172
177
  ];
173
- export type TIndexTuple<T extends TSchema[], K extends Key> = K extends keyof T ? [T[K]] : [
178
+ export type TIndexRestMany<T extends TSchema, K extends Key[]> = K extends [infer L, ...infer R] ? [TIndexType<T, Assert<L, Key>>, ...TIndexRestMany<T, Assert<R, Key[]>>] : [
174
179
  ];
175
- export type TIndexComposite<T extends TSchema[], K extends Key> = T extends [infer L, ...infer R] ? [...TIndexKey<AssertType<L>, K>, ...TIndexComposite<AssertRest<R>, K>] : [
176
- ];
177
- export type TIndexKey<T extends TSchema, K extends Key> = T extends TRecursive<infer S> ? TIndexKey<S, K> : T extends TIntersect<infer S> ? TIndexComposite<S, K> : T extends TUnion<infer S> ? TIndexComposite<S, K> : T extends TObject<infer S> ? TIndexProperty<S, K> : T extends TTuple<infer S> ? TIndexTuple<S, K> : T extends TArray<infer S> ? S : [
178
- ];
179
- export type TIndexKeys<T extends TSchema, K extends Key[]> = K extends [infer L, ...infer R] ? [
180
- ...TIndexKey<T, Assert<L, Key>>,
181
- ...TIndexKeys<T, Assert<R, Key[]>>
182
- ] : [
183
- ];
184
- export type TIndexFromKeyTuple<T extends TSchema, K extends Key[]> = TIndexKeys<T, K> extends infer R ? T extends TRecursive<infer S> ? TIndexFromKeyTuple<S, K> : T extends TTuple ? UnionType<AssertRest<R>> : T extends TIntersect ? UnionType<AssertRest<R>> : T extends TUnion ? UnionType<AssertRest<R>> : T extends TObject ? UnionType<AssertRest<R>> : T extends TArray ? UnionType<AssertRest<R>> : TNever : TNever;
180
+ export type TIndexReduce<T extends TSchema, K extends Key[]> = T extends TRecursive<infer S> ? TIndexReduce<S, K> : T extends TIntersect ? UnionType<Flat<TIndexRestMany<T, K>>> : T extends TUnion ? UnionType<Flat<TIndexRestMany<T, K>>> : T extends TObject ? UnionType<Flat<TIndexRestMany<T, K>>> : T extends TTuple ? UnionType<Flat<TIndexRestMany<T, K>>> : TNever;
185
181
  export type TIndex<T extends TSchema, K extends TSchema> = [
186
182
  T,
187
183
  K
188
184
  ] extends [TTuple, TNumber] ? UnionType<Assert<T['items'], TSchema[]>> : [
189
185
  T,
190
186
  K
191
- ] extends [TArray, TNumber] ? AssertType<T['items']> : K extends TTemplateLiteral ? TIndexFromKeyTuple<T, TTemplateLiteralKeyTuple<K>> : K extends TUnion<TLiteral<Key>[]> ? TIndexFromKeyTuple<T, TUnionLiteral<K>> : K extends TLiteral<Key> ? TIndexFromKeyTuple<T, [K['const']]> : TNever;
187
+ ] extends [TArray, TNumber] ? AssertType<T['items']> : K extends TTemplateLiteral ? TIndexReduce<T, TTemplateLiteralKeyRest<K>> : K extends TUnion<TLiteral<Key>[]> ? TIndexReduce<T, TUnionLiteralKeyRest<K>> : K extends TLiteral<Key> ? TIndexReduce<T, [K['const']]> : TNever;
192
188
  export interface TInteger extends TSchema, NumericOptions<number> {
193
189
  [Kind]: 'Integer';
194
190
  static: number;
@@ -379,7 +375,7 @@ export type TTemplateLiteralConst<T, Acc extends string> = T extends TUnion<infe
379
375
  [K in keyof U]: TTemplateLiteralUnion<Assert<[U[K]], TTemplateLiteralKind[]>, Acc>;
380
376
  }[number] : T extends TTemplateLiteral ? `${Static<T>}` : T extends TLiteral<infer U> ? `${U}` : T extends TString ? `${string}` : T extends TNumber ? `${number}` : T extends TBigInt ? `${bigint}` : T extends TBoolean ? `${boolean}` : never;
381
377
  export type TTemplateLiteralUnion<T extends TTemplateLiteralKind[], Acc extends string = ''> = T extends [infer L, ...infer R] ? `${TTemplateLiteralConst<L, Acc>}${TTemplateLiteralUnion<Assert<R, TTemplateLiteralKind[]>, Acc>}` : Acc;
382
- export type TTemplateLiteralKeyTuple<T extends TTemplateLiteral> = Assert<UnionToTuple<Static<T>>, Key[]>;
378
+ export type TTemplateLiteralKeyRest<T extends TTemplateLiteral> = Assert<UnionToTuple<Static<T>>, Key[]>;
383
379
  export interface TTemplateLiteral<T extends TTemplateLiteralKind[] = TTemplateLiteralKind[]> extends TSchema {
384
380
  [Kind]: 'TemplateLiteral';
385
381
  static: TTemplateLiteralUnion<T>;
@@ -405,7 +401,7 @@ export interface TUndefined extends TSchema {
405
401
  }
406
402
  export type TLiteralUnionReduce<T extends TLiteral<string | number>[]> = T extends [infer L, ...infer R] ? [Assert<L, TLiteral<string | number>>['const'], ...TLiteralUnionReduce<Assert<R, TLiteral<string | number>[]>>] : [
407
403
  ];
408
- export type TUnionLiteral<T extends TUnion<TLiteral<string | number>[]>> = T extends TUnion<infer S> ? TLiteralUnionReduce<Assert<S, TLiteral<string | number>[]>> : [
404
+ export type TUnionLiteralKeyRest<T extends TUnion<TLiteral<string | number>[]>> = T extends TUnion<infer S> ? TLiteralUnionReduce<Assert<S, TLiteral<string | number>[]>> : [
409
405
  ];
410
406
  export type TUnionTemplateLiteral<T extends TTemplateLiteral, S extends string = Static<T>> = Ensure<UnionType<Assert<UnionToTuple<{
411
407
  [K in S]: TLiteral<K>;
@@ -444,7 +440,7 @@ export interface TVoid extends TSchema {
444
440
  type: 'null';
445
441
  typeOf: 'Void';
446
442
  }
447
- /** Creates a TypeScript static type from a TypeBox type */
443
+ /** Infers a static type from a TypeBox type */
448
444
  export type Static<T extends TSchema, P extends unknown[] = []> = (T & {
449
445
  params: P;
450
446
  })['static'];
@@ -577,7 +573,7 @@ export declare namespace TypeClone {
577
573
  function Clone<T extends TSchema>(schema: T, options: SchemaOptions): T;
578
574
  }
579
575
  export declare namespace IndexedAccessor {
580
- function Resolve(schema: TSchema, keys: (string | number)[]): TSchema[];
576
+ function Resolve(schema: TSchema, keys: Key[], options?: SchemaOptions): TSchema;
581
577
  }
582
578
  export declare namespace ObjectMap {
583
579
  function Map<T = TSchema>(schema: TSchema, callback: (object: TObject) => TObject, options: SchemaOptions): T;
@@ -664,7 +660,7 @@ export declare class StandardTypeBuilder extends TypeBuilder {
664
660
  /** `[Standard]` Extracts from the left type any type that is assignable to the right */
665
661
  Extract<L extends TSchema, R extends TSchema>(left: L, right: R, options?: SchemaOptions): TExtract<L, R>;
666
662
  /** `[Standard]` Returns indexed property types for the given keys */
667
- Index<T extends TSchema, K extends (keyof Static<T>)[]>(schema: T, keys: [...K], options?: SchemaOptions): TIndexFromKeyTuple<T, Assert<K, Key[]>>;
663
+ Index<T extends TSchema, K extends (keyof Static<T>)[]>(schema: T, keys: [...K], options?: SchemaOptions): TIndexReduce<T, Assert<K, Key[]>>;
668
664
  /** `[Standard]` Returns indexed property types for the given keys */
669
665
  Index<T extends TSchema, K extends TSchema>(schema: T, key: K, options?: SchemaOptions): TIndex<T, K>;
670
666
  /** `[Standard]` Creates an Integer type */
@@ -691,11 +687,11 @@ export declare class StandardTypeBuilder extends TypeBuilder {
691
687
  /** `[Standard]` Creates a mapped type whose keys are omitted from the given type */
692
688
  Omit<T extends TSchema, K extends (keyof Static<T>)[]>(schema: T, keys: readonly [...K], options?: SchemaOptions): TOmit<T, K[number]>;
693
689
  /** `[Standard]` Creates a mapped type whose keys are omitted from the given type */
694
- Omit<T extends TSchema, K extends TUnion<TLiteral<string>[]>>(schema: T, keys: K, options?: SchemaOptions): TOmit<T, TUnionLiteral<K>[number]>;
690
+ Omit<T extends TSchema, K extends TUnion<TLiteral<string>[]>>(schema: T, keys: K, options?: SchemaOptions): TOmit<T, TUnionLiteralKeyRest<K>[number]>;
695
691
  /** `[Standard]` Creates a mapped type whose keys are omitted from the given type */
696
692
  Omit<T extends TSchema, K extends TLiteral<string>>(schema: T, key: K, options?: SchemaOptions): TOmit<T, K['const']>;
697
693
  /** `[Standard]` Creates a mapped type whose keys are omitted from the given type */
698
- Omit<T extends TSchema, K extends TTemplateLiteral>(schema: T, key: K, options?: SchemaOptions): TOmit<T, TTemplateLiteralKeyTuple<K>[number]>;
694
+ Omit<T extends TSchema, K extends TTemplateLiteral>(schema: T, key: K, options?: SchemaOptions): TOmit<T, TTemplateLiteralKeyRest<K>[number]>;
699
695
  /** `[Standard]` Creates a mapped type whose keys are omitted from the given type */
700
696
  Omit<T extends TSchema, K extends TNever>(schema: T, key: K, options?: SchemaOptions): TOmit<T, never>;
701
697
  /** `[Standard]` Creates a mapped type where all properties are Optional */
@@ -703,11 +699,11 @@ export declare class StandardTypeBuilder extends TypeBuilder {
703
699
  /** `[Standard]` Creates a mapped type whose keys are picked from the given type */
704
700
  Pick<T extends TSchema, K extends (keyof Static<T>)[]>(schema: T, keys: readonly [...K], options?: SchemaOptions): TPick<T, K[number]>;
705
701
  /** `[Standard]` Creates a mapped type whose keys are picked from the given type */
706
- Pick<T extends TSchema, K extends TUnion<TLiteral<string>[]>>(schema: T, keys: K, options?: SchemaOptions): TPick<T, TUnionLiteral<K>[number]>;
702
+ Pick<T extends TSchema, K extends TUnion<TLiteral<string>[]>>(schema: T, keys: K, options?: SchemaOptions): TPick<T, TUnionLiteralKeyRest<K>[number]>;
707
703
  /** `[Standard]` Creates a mapped type whose keys are picked from the given type */
708
704
  Pick<T extends TSchema, K extends TLiteral<string>>(schema: T, key: K, options?: SchemaOptions): TPick<T, K['const']>;
709
705
  /** `[Standard]` Creates a mapped type whose keys are picked from the given type */
710
- Pick<T extends TSchema, K extends TTemplateLiteral>(schema: T, key: K, options?: SchemaOptions): TPick<T, TTemplateLiteralKeyTuple<K>[number]>;
706
+ Pick<T extends TSchema, K extends TTemplateLiteral>(schema: T, key: K, options?: SchemaOptions): TPick<T, TTemplateLiteralKeyRest<K>[number]>;
711
707
  /** `[Standard]` Creates a mapped type whose keys are picked from the given type */
712
708
  Pick<T extends TSchema, K extends TNever>(schema: T, key: K, options?: SchemaOptions): TPick<T, never>;
713
709
  /** `[Standard]` Creates a Record type */
package/typebox.js CHANGED
@@ -1405,18 +1405,28 @@ var TypeClone;
1405
1405
  var IndexedAccessor;
1406
1406
  (function (IndexedAccessor) {
1407
1407
  function Intersect(schema, key) {
1408
- return schema.allOf.reduce((acc, schema) => [...acc, ...Visit(schema, key)], []);
1408
+ const schemas = schema.allOf.reduce((acc, schema) => {
1409
+ const indexed = Visit(schema, key);
1410
+ return indexed[exports.Kind] === 'Never' ? acc : [...acc, indexed];
1411
+ }, []);
1412
+ return exports.Type.Intersect(schemas);
1409
1413
  }
1410
1414
  function Union(schema, key) {
1411
- return schema.anyOf.reduce((acc, schema) => [...acc, ...Visit(schema, key)], []);
1415
+ const schemas = schema.anyOf.map((schema) => Visit(schema, key));
1416
+ return exports.Type.Union(schemas);
1412
1417
  }
1413
1418
  function Object(schema, key) {
1414
- const keys = globalThis.Object.getOwnPropertyNames(schema.properties).filter((key_) => key_ === key);
1415
- return keys.map((key) => schema.properties[key]);
1419
+ const property = schema.properties[key];
1420
+ return property === undefined ? exports.Type.Never() : exports.Type.Union([property]);
1416
1421
  }
1417
1422
  function Tuple(schema, key) {
1418
- const items = schema.items === undefined ? [] : schema.items;
1419
- return items.filter((_, index) => index.toString() === key);
1423
+ const items = schema.items;
1424
+ if (items === undefined)
1425
+ return exports.Type.Never();
1426
+ const element = items[key]; //
1427
+ if (element === undefined)
1428
+ return exports.Type.Never();
1429
+ return element;
1420
1430
  }
1421
1431
  function Visit(schema, key) {
1422
1432
  if (schema[exports.Kind] === 'Intersect')
@@ -1427,10 +1437,10 @@ var IndexedAccessor;
1427
1437
  return Object(schema, key);
1428
1438
  if (schema[exports.Kind] === 'Tuple')
1429
1439
  return Tuple(schema, key);
1430
- return [];
1440
+ return exports.Type.Never();
1431
1441
  }
1432
- function Resolve(schema, keys) {
1433
- return keys.reduce((acc, key) => [...acc, ...Visit(schema, key.toString())], []);
1442
+ function Resolve(schema, keys, options = {}) {
1443
+ return exports.Type.Union(keys.map((key) => Visit(schema, key.toString())));
1434
1444
  }
1435
1445
  IndexedAccessor.Resolve = Resolve;
1436
1446
  })(IndexedAccessor = exports.IndexedAccessor || (exports.IndexedAccessor = {}));
@@ -1977,18 +1987,19 @@ class StandardTypeBuilder extends TypeBuilder {
1977
1987
  }
1978
1988
  /** `[Standard]` Returns indexed property types for the given keys */
1979
1989
  Index(schema, unresolved, options = {}) {
1980
- const keys = KeyArrayResolver.Resolve(unresolved);
1981
1990
  if (TypeGuard.TArray(schema) && TypeGuard.TNumber(unresolved)) {
1982
1991
  return TypeClone.Clone(schema.items, options);
1983
1992
  }
1984
- if (TypeGuard.TTuple(schema) && TypeGuard.TNumber(unresolved)) {
1993
+ else if (TypeGuard.TTuple(schema) && TypeGuard.TNumber(unresolved)) {
1985
1994
  const items = schema.items === undefined ? [] : schema.items;
1986
1995
  const cloned = items.map((schema) => TypeClone.Clone(schema, {}));
1987
1996
  return this.Union(cloned, options);
1988
1997
  }
1989
- const resolved = IndexedAccessor.Resolve(schema, keys);
1990
- const cloned = resolved.map((schema) => TypeClone.Clone(schema, {}));
1991
- return this.Union(cloned, options);
1998
+ else {
1999
+ const keys = KeyArrayResolver.Resolve(unresolved);
2000
+ const clone = TypeClone.Clone(schema, {});
2001
+ return IndexedAccessor.Resolve(clone, keys, options);
2002
+ }
1992
2003
  }
1993
2004
  /** `[Standard]` Creates an Integer type */
1994
2005
  Integer(options = {}) {