@sinclair/typebox 0.30.0-dev-3 → 0.30.0-dev-5

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.30.0-dev-3",
3
+ "version": "0.30.0-dev-5",
4
4
  "description": "JSONSchema Type Builder with Static Type Resolution for TypeScript",
5
5
  "keywords": [
6
6
  "typescript",
package/readme.md CHANGED
@@ -63,7 +63,7 @@ type T = Static<typeof T> // type T = {
63
63
 
64
64
  ## Overview
65
65
 
66
- TypeBox is a runtime type builder that creates in-memory JSON Schema objects that can be statically inferred as TypeScript types. The schemas produced by this library are designed to match the static type assertion rules of the TypeScript compiler. TypeBox enables one to create a unified type that can be statically checked by TypeScript and runtime asserted using standard JSON Schema validation.
66
+ TypeBox is a runtime type builder that creates in-memory JSON Schema objects that can be statically inferred as TypeScript types. The schemas produced by this library are designed to match the static type assertion rules of the TypeScript language. TypeBox allows one to create a unified type that can be statically checked by TypeScript and runtime asserted using standard JSON Schema validation.
67
67
 
68
68
  This library is designed to enable JSON schema to compose with the same flexibility as TypeScript's type system. It can be used as a simple tool to build up complex schemas or integrated into REST or RPC services to help validate data received over the wire.
69
69
 
@@ -72,6 +72,7 @@ License MIT
72
72
  ## Contents
73
73
  - [Install](#install)
74
74
  - [Overview](#overview)
75
+ - [Features](#features)
75
76
  - [Usage](#usage)
76
77
  - [Types](#types)
77
78
  - [Standard](#types-standard)
@@ -102,7 +103,6 @@ License MIT
102
103
  - [Errors](#values-errors)
103
104
  - [Mutate](#values-mutate)
104
105
  - [Pointer](#values-pointer)
105
- - [Transform](#values-transform)
106
106
  - [TypeCheck](#typecheck)
107
107
  - [Ajv](#typecheck-ajv)
108
108
  - [TypeCompiler](#typecheck-typecompiler)
@@ -110,7 +110,7 @@ License MIT
110
110
  - [Types](#typesystem-types)
111
111
  - [Formats](#typesystem-formats)
112
112
  - [Policies](#typesystem-policies)
113
- - [Workbench](#workbench)
113
+ - [Transform](#Transform)
114
114
  - [Ecosystem](#ecosystem)
115
115
  - [Benchmark](#benchmark)
116
116
  - [Compile](#benchmark-compile)
@@ -1457,13 +1457,13 @@ TypeSystem.AllowArrayObjects = true
1457
1457
  TypeSystem.AllowNaN = true
1458
1458
  ```
1459
1459
 
1460
- <a name='workbench'></a>
1460
+ <a name='transform'></a>
1461
1461
 
1462
- ## Workbench
1462
+ ## TypeBox Transform
1463
1463
 
1464
- TypeBox offers a web based code generation tool that can be used to convert TypeScript types into TypeBox types as well as a variety of other runtime type representations.
1464
+ TypeBox offers a small web based code generation tool that can be used to convert TypeScript types into TypeBox types as well as a variety of other runtime type representations.
1465
1465
 
1466
- [Workbench Link Here](https://sinclairzx81.github.io/typebox-workbench/)
1466
+ [TypeBox Transform Link Here](https://sinclairzx81.github.io/typebox-transform/)
1467
1467
 
1468
1468
  <a name='ecosystem'></a>
1469
1469
 
@@ -1586,11 +1586,11 @@ The following table lists esbuild compiled and minified sizes for each TypeBox m
1586
1586
  ┌──────────────────────┬────────────┬────────────┬─────────────┐
1587
1587
  │ (index) │ Compiled │ Minified │ Compression │
1588
1588
  ├──────────────────────┼────────────┼────────────┼─────────────┤
1589
- │ typebox/compiler │ '128.2 kb' │ ' 58.2 kb' │ '2.20 x' │
1590
- │ typebox/errors │ '110.4 kb' │ ' 49.5 kb' │ '2.23 x' │
1591
- │ typebox/system │ ' 75.2 kb' │ ' 31.1 kb' │ '2.42 x' │
1592
- │ typebox/value │ '179.6 kb' │ ' 78.7 kb' │ '2.28 x' │
1593
- │ typebox │ ' 74.1 kb' │ ' 30.6 kb' │ '2.42 x' │
1589
+ │ typebox/compiler │ '129.4 kb' │ ' 58.6 kb' │ '2.21 x' │
1590
+ │ typebox/errors │ '111.6 kb' │ ' 50.1 kb' │ '2.23 x' │
1591
+ │ typebox/system │ ' 76.5 kb' │ ' 31.7 kb' │ '2.41 x' │
1592
+ │ typebox/value │ '180.7 kb' │ ' 79.3 kb' │ '2.28 x' │
1593
+ │ typebox │ ' 75.4 kb' │ ' 31.3 kb' │ '2.41 x' │
1594
1594
  └──────────────────────┴────────────┴────────────┴─────────────┘
1595
1595
  ```
1596
1596
 
package/typebox.d.ts CHANGED
@@ -104,6 +104,8 @@ export interface TAsyncIterator<T extends TSchema = TSchema> extends TSchema {
104
104
  type: 'AsyncIterator';
105
105
  items: T;
106
106
  }
107
+ export type TAwaitedRest<T extends TSchema[]> = T extends [infer L, ...infer R] ? [TAwaited<AssertType<L>>, ...TAwaitedRest<AssertRest<R>>] : [];
108
+ export type TAwaited<T extends TSchema> = T extends TIntersect<infer S> ? TIntersect<TAwaitedRest<S>> : T extends TUnion<infer S> ? TUnion<TAwaitedRest<S>> : T extends TPromise<infer S> ? TAwaited<S> : T;
107
109
  export interface TBigInt extends TSchema, NumericOptions<bigint> {
108
110
  [Kind]: 'BigInt';
109
111
  static: bigint;
@@ -276,11 +278,11 @@ export interface TObject<T extends TProperties = TProperties> extends TSchema, O
276
278
  properties: T;
277
279
  required?: string[];
278
280
  }
279
- export type TOmitArray<T extends TSchema[], K extends keyof any> = AssertRest<{
281
+ export type TOmitProperties<T extends TProperties, K extends keyof any> = Evaluate<AssertProperties<Omit<T, K>>>;
282
+ export type TOmitRest<T extends TSchema[], K extends keyof any> = AssertRest<{
280
283
  [K2 in keyof T]: TOmit<AssertType<T[K2]>, K>;
281
284
  }>;
282
- export type TOmitProperties<T extends TProperties, K extends keyof any> = Evaluate<AssertProperties<Omit<T, K>>>;
283
- export type TOmit<T extends TSchema = TSchema, K extends keyof any = keyof any> = T extends TRecursive<infer S> ? TRecursive<TOmit<S, K>> : T extends TIntersect<infer S> ? TIntersect<TOmitArray<S, K>> : T extends TUnion<infer S> ? TUnion<TOmitArray<S, K>> : T extends TObject<infer S> ? TObject<TOmitProperties<S, K>> : T;
285
+ export type TOmit<T extends TSchema = TSchema, K extends keyof any = keyof any> = T extends TRecursive<infer S> ? TRecursive<TOmit<S, K>> : T extends TIntersect<infer S> ? TIntersect<TOmitRest<S, K>> : T extends TUnion<infer S> ? TUnion<TOmitRest<S, K>> : T extends TObject<infer S> ? TObject<TOmitProperties<S, K>> : T;
284
286
  export type TParameters<T extends TFunction> = Ensure<TTuple<T['parameters']>>;
285
287
  export type TPartialObjectArray<T extends TObject[]> = AssertRest<{
286
288
  [K in keyof T]: TPartial<AssertType<T[K], TObject>>;
@@ -292,13 +294,13 @@ export type TPartialProperties<T extends TProperties> = Evaluate<AssertPropertie
292
294
  [K in keyof T]: TOptional<T[K]>;
293
295
  }>>;
294
296
  export type TPartial<T extends TSchema> = T extends TRecursive<infer S> ? TRecursive<TPartial<S>> : T extends TIntersect<infer S> ? TIntersect<TPartialArray<S>> : T extends TUnion<infer S> ? TUnion<TPartialArray<S>> : T extends TObject<infer S> ? TObject<TPartialProperties<S>> : T;
295
- export type TPickArray<T extends TSchema[], K extends keyof any> = {
296
- [K2 in keyof T]: TPick<AssertType<T[K2]>, K>;
297
- };
298
297
  export type TPickProperties<T extends TProperties, K extends keyof any> = Pick<T, Assert<Extract<K, keyof T>, keyof T>> extends infer R ? ({
299
298
  [K in keyof R]: AssertType<R[K]> extends TSchema ? R[K] : never;
300
299
  }) : never;
301
- export type TPick<T extends TSchema = TSchema, K extends keyof any = keyof any> = T extends TRecursive<infer S> ? TRecursive<TPick<S, K>> : T extends TIntersect<infer S> ? TIntersect<TPickArray<S, K>> : T extends TUnion<infer S> ? TUnion<TPickArray<S, K>> : T extends TObject<infer S> ? TObject<TPickProperties<S, K>> : T;
300
+ export type TPickRest<T extends TSchema[], K extends keyof any> = {
301
+ [K2 in keyof T]: TPick<AssertType<T[K2]>, K>;
302
+ };
303
+ export type TPick<T extends TSchema = TSchema, K extends keyof any = keyof any> = T extends TRecursive<infer S> ? TRecursive<TPick<S, K>> : T extends TIntersect<infer S> ? TIntersect<TPickRest<S, K>> : T extends TUnion<infer S> ? TUnion<TPickRest<S, K>> : T extends TObject<infer S> ? TObject<TPickProperties<S, K>> : T;
302
304
  export interface TPromise<T extends TSchema = TSchema> extends TSchema {
303
305
  [Kind]: 'Promise';
304
306
  static: Promise<Static<T, this['params']>>;
@@ -601,7 +603,7 @@ export declare namespace TypeExtends {
601
603
  /** Specialized Clone for Types */
602
604
  export declare namespace TypeClone {
603
605
  /** Clones a type. */
604
- function Clone<T extends TSchema>(schema: T, options: SchemaOptions): T;
606
+ function Clone<T extends TSchema>(schema: T, options?: SchemaOptions): T;
605
607
  }
606
608
  export declare namespace IndexedAccessor {
607
609
  function Resolve(schema: TSchema, keys: Key[], options?: SchemaOptions): TSchema;
@@ -685,6 +687,8 @@ export declare class StandardTypeBuilder extends TypeBuilder {
685
687
  Array<T extends TSchema>(items: T, options?: ArrayOptions): TArray<T>;
686
688
  /** `[Standard]` Creates a Boolean type */
687
689
  Boolean(options?: SchemaOptions): TBoolean;
690
+ /** `[Standard]` Maps a literal strings first character to uppercase */
691
+ Capitalize<T extends TLiteral<string>>(schema: T, options?: SchemaOptions): TLiteral<Capitalize<T['const']>>;
688
692
  /** `[Standard]` Creates a Composite object type. */
689
693
  Composite<T extends TObject[]>(objects: [...T], options?: ObjectOptions): TComposite<T>;
690
694
  /** `[Standard]` Creates a Enum type */
@@ -720,6 +724,8 @@ export declare class StandardTypeBuilder extends TypeBuilder {
720
724
  KeyOf<T extends TSchema>(schema: T, options?: SchemaOptions): TKeyOf<T>;
721
725
  /** `[Standard]` Creates a Literal type */
722
726
  Literal<T extends TLiteralValue>(value: T, options?: SchemaOptions): TLiteral<T>;
727
+ /** `[Standard]` Maps a literal string to lowercase */
728
+ Lowercase<T extends TLiteral<string>>(schema: T, options?: SchemaOptions): TLiteral<Lowercase<T['const']>>;
723
729
  /** `[Standard]` Creates a Never type */
724
730
  Never(options?: SchemaOptions): TNever;
725
731
  /** `[Standard]` Creates a Not type */
@@ -780,6 +786,8 @@ export declare class StandardTypeBuilder extends TypeBuilder {
780
786
  TemplateLiteral<T extends TTemplateLiteralKind[]>(kinds: [...T], options?: SchemaOptions): TTemplateLiteral<T>;
781
787
  /** `[Standard]` Creates a Tuple type */
782
788
  Tuple<T extends TSchema[]>(items: [...T], options?: SchemaOptions): TTuple<T>;
789
+ /** `[Standard]` Maps a literal strings first character to lowercase */
790
+ Uncapitalize<T extends TLiteral<string>>(schema: T, options?: SchemaOptions): TLiteral<Uncapitalize<T['const']>>;
783
791
  /** `[Standard]` Creates a Union type */
784
792
  Union(anyOf: [], options?: SchemaOptions): TNever;
785
793
  /** `[Standard]` Creates a Union type */
@@ -792,10 +800,14 @@ export declare class StandardTypeBuilder extends TypeBuilder {
792
800
  Unknown(options?: SchemaOptions): TUnknown;
793
801
  /** `[Standard]` Creates a Unsafe type that infers for the generic argument */
794
802
  Unsafe<T>(options?: UnsafeOptions): TUnsafe<T>;
803
+ /** `[Standard]` Maps a literal string to uppercase */
804
+ Uppercase<T extends TLiteral<string>>(schema: T, options?: SchemaOptions): TLiteral<Uppercase<T['const']>>;
795
805
  }
796
806
  export declare class ExtendedTypeBuilder extends StandardTypeBuilder {
797
807
  /** `[Extended]` Creates a AsyncIterator type */
798
808
  AsyncIterator<T extends TSchema>(items: T, options?: SchemaOptions): TAsyncIterator<T>;
809
+ /** `[Extended]` Recursively unwraps Promise from the given type. */
810
+ Awaited<T extends TSchema>(schema: T, options?: SchemaOptions): TAwaited<T>;
799
811
  /** `[Extended]` Creates a BigInt type */
800
812
  BigInt(options?: NumericOptions<bigint>): TBigInt;
801
813
  /** `[Extended]` Extracts the ConstructorParameters from the given Constructor type */
package/typebox.js CHANGED
@@ -222,12 +222,12 @@ var TypeGuard;
222
222
  schema.type === 'array' &&
223
223
  IsOptionalString(schema.$id) &&
224
224
  TSchema(schema.items) &&
225
- IsOptionalSchema(schema.contains) &&
226
- IsOptionalNumber(schema.minContains) &&
227
- IsOptionalNumber(schema.maxContains) &&
228
225
  IsOptionalNumber(schema.minItems) &&
229
226
  IsOptionalNumber(schema.maxItems) &&
230
- IsOptionalBoolean(schema.uniqueItems));
227
+ IsOptionalBoolean(schema.uniqueItems) &&
228
+ IsOptionalSchema(schema.contains) &&
229
+ IsOptionalNumber(schema.minContains) &&
230
+ IsOptionalNumber(schema.maxContains));
231
231
  }
232
232
  TypeGuard.TArray = TArray;
233
233
  /** Returns true if the given schema is TAsyncIterator */
@@ -1369,7 +1369,7 @@ var TypeClone;
1369
1369
  return value;
1370
1370
  }
1371
1371
  /** Clones a type. */
1372
- function Clone(schema, options) {
1372
+ function Clone(schema, options = {}) {
1373
1373
  return { ...Visit(schema), ...options };
1374
1374
  }
1375
1375
  TypeClone.Clone = Clone;
@@ -1381,7 +1381,7 @@ var IndexedAccessor;
1381
1381
  (function (IndexedAccessor) {
1382
1382
  function OptionalUnwrap(schema) {
1383
1383
  return schema.map((schema) => {
1384
- const { [exports.Optional]: _, ...clone } = TypeClone.Clone(schema, {});
1384
+ const { [exports.Optional]: _, ...clone } = TypeClone.Clone(schema);
1385
1385
  return clone;
1386
1386
  });
1387
1387
  }
@@ -1477,7 +1477,7 @@ var ObjectMap;
1477
1477
  return schema;
1478
1478
  }
1479
1479
  function Map(schema, callback, options) {
1480
- return { ...Visit(TypeClone.Clone(schema, {}), callback), ...options };
1480
+ return { ...Visit(TypeClone.Clone(schema), callback), ...options };
1481
1481
  }
1482
1482
  ObjectMap.Map = Map;
1483
1483
  })(ObjectMap || (exports.ObjectMap = ObjectMap = {}));
@@ -1931,11 +1931,11 @@ class StandardTypeBuilder extends TypeBuilder {
1931
1931
  }
1932
1932
  /** `[Standard]` Creates a Readonly property */
1933
1933
  Readonly(schema) {
1934
- return { ...TypeClone.Clone(schema, {}), [exports.Readonly]: 'Readonly' };
1934
+ return { ...TypeClone.Clone(schema), [exports.Readonly]: 'Readonly' };
1935
1935
  }
1936
1936
  /** `[Standard]` Creates an Optional property */
1937
1937
  Optional(schema) {
1938
- return { ...TypeClone.Clone(schema, {}), [exports.Optional]: 'Optional' };
1938
+ return { ...TypeClone.Clone(schema), [exports.Optional]: 'Optional' };
1939
1939
  }
1940
1940
  // ------------------------------------------------------------------------
1941
1941
  // Types
@@ -1946,12 +1946,17 @@ class StandardTypeBuilder extends TypeBuilder {
1946
1946
  }
1947
1947
  /** `[Standard]` Creates an Array type */
1948
1948
  Array(items, options = {}) {
1949
- return this.Create({ ...options, [exports.Kind]: 'Array', type: 'array', items: TypeClone.Clone(items, {}) });
1949
+ return this.Create({ ...options, [exports.Kind]: 'Array', type: 'array', items: TypeClone.Clone(items) });
1950
1950
  }
1951
1951
  /** `[Standard]` Creates a Boolean type */
1952
1952
  Boolean(options = {}) {
1953
1953
  return this.Create({ ...options, [exports.Kind]: 'Boolean', type: 'boolean' });
1954
1954
  }
1955
+ /** `[Standard]` Maps a literal strings first character to uppercase */
1956
+ Capitalize(schema, options = {}) {
1957
+ const [first, rest] = [schema.const.slice(0, 1), schema.const.slice(1)];
1958
+ return exports.Type.Literal(`${first.toUpperCase()}${rest}`, options);
1959
+ }
1955
1960
  /** `[Standard]` Creates a Composite object type. */
1956
1961
  Composite(objects, options) {
1957
1962
  const intersect = exports.Type.Intersect(objects, {});
@@ -2012,12 +2017,12 @@ class StandardTypeBuilder extends TypeBuilder {
2012
2017
  }
2013
2018
  else if (TypeGuard.TTuple(schema) && TypeGuard.TNumber(unresolved)) {
2014
2019
  const items = ValueGuard.IsUndefined(schema.items) ? [] : schema.items;
2015
- const cloned = items.map((schema) => TypeClone.Clone(schema, {}));
2020
+ const cloned = items.map((schema) => TypeClone.Clone(schema));
2016
2021
  return this.Union(cloned, options);
2017
2022
  }
2018
2023
  else {
2019
2024
  const keys = KeyArrayResolver.Resolve(unresolved);
2020
- const clone = TypeClone.Clone(schema, {});
2025
+ const clone = TypeClone.Clone(schema);
2021
2026
  return IndexedAccessor.Resolve(clone, keys, options);
2022
2027
  }
2023
2028
  }
@@ -2031,8 +2036,8 @@ class StandardTypeBuilder extends TypeBuilder {
2031
2036
  if (allOf.length === 1)
2032
2037
  return TypeClone.Clone(allOf[0], options);
2033
2038
  const objects = allOf.every((schema) => TypeGuard.TObject(schema));
2034
- const cloned = allOf.map((schema) => TypeClone.Clone(schema, {}));
2035
- const clonedUnevaluatedProperties = TypeGuard.TSchema(options.unevaluatedProperties) ? { unevaluatedProperties: TypeClone.Clone(options.unevaluatedProperties, {}) } : {};
2039
+ const cloned = allOf.map((schema) => TypeClone.Clone(schema));
2040
+ const clonedUnevaluatedProperties = TypeGuard.TSchema(options.unevaluatedProperties) ? { unevaluatedProperties: TypeClone.Clone(options.unevaluatedProperties) } : {};
2036
2041
  if (options.unevaluatedProperties === false || TypeGuard.TSchema(options.unevaluatedProperties) || objects) {
2037
2042
  return this.Create({ ...options, ...clonedUnevaluatedProperties, [exports.Kind]: 'Intersect', type: 'object', allOf: cloned });
2038
2043
  }
@@ -2070,6 +2075,10 @@ class StandardTypeBuilder extends TypeBuilder {
2070
2075
  Literal(value, options = {}) {
2071
2076
  return this.Create({ ...options, [exports.Kind]: 'Literal', const: value, type: typeof value });
2072
2077
  }
2078
+ /** `[Standard]` Maps a literal string to lowercase */
2079
+ Lowercase(schema, options = {}) {
2080
+ return exports.Type.Literal(schema.const.toLowerCase(), options);
2081
+ }
2073
2082
  /** `[Standard]` Creates a Never type */
2074
2083
  Never(options = {}) {
2075
2084
  return this.Create({ ...options, [exports.Kind]: 'Never', not: {} });
@@ -2091,8 +2100,8 @@ class StandardTypeBuilder extends TypeBuilder {
2091
2100
  const propertyKeys = Object.getOwnPropertyNames(properties);
2092
2101
  const optionalKeys = propertyKeys.filter((key) => TypeGuard.TOptional(properties[key]));
2093
2102
  const requiredKeys = propertyKeys.filter((name) => !optionalKeys.includes(name));
2094
- const clonedAdditionalProperties = TypeGuard.TSchema(options.additionalProperties) ? { additionalProperties: TypeClone.Clone(options.additionalProperties, {}) } : {};
2095
- const clonedProperties = propertyKeys.reduce((acc, key) => ({ ...acc, [key]: TypeClone.Clone(properties[key], {}) }), {});
2103
+ const clonedAdditionalProperties = TypeGuard.TSchema(options.additionalProperties) ? { additionalProperties: TypeClone.Clone(options.additionalProperties) } : {};
2104
+ const clonedProperties = propertyKeys.reduce((acc, key) => ({ ...acc, [key]: TypeClone.Clone(properties[key]) }), {});
2096
2105
  if (requiredKeys.length > 0) {
2097
2106
  return this.Create({ ...options, ...clonedAdditionalProperties, [exports.Kind]: 'Object', type: 'object', properties: clonedProperties, required: requiredKeys });
2098
2107
  }
@@ -2103,17 +2112,17 @@ class StandardTypeBuilder extends TypeBuilder {
2103
2112
  Omit(schema, unresolved, options = {}) {
2104
2113
  const keys = KeyArrayResolver.Resolve(unresolved);
2105
2114
  // prettier-ignore
2106
- return ObjectMap.Map(TypeClone.Clone(schema, {}), (schema) => {
2107
- if (schema.required) {
2108
- schema.required = schema.required.filter((key) => !keys.includes(key));
2109
- if (schema.required.length === 0)
2110
- delete schema.required;
2115
+ return ObjectMap.Map(TypeClone.Clone(schema), (object) => {
2116
+ if (ValueGuard.IsArray(object.required)) {
2117
+ object.required = object.required.filter((key) => !keys.includes(key));
2118
+ if (object.required.length === 0)
2119
+ delete object.required;
2111
2120
  }
2112
- for (const key of Object.getOwnPropertyNames(schema.properties)) {
2121
+ for (const key of Object.getOwnPropertyNames(object.properties)) {
2113
2122
  if (keys.includes(key))
2114
- delete schema.properties[key];
2123
+ delete object.properties[key];
2115
2124
  }
2116
- return this.Create(schema);
2125
+ return this.Create(object);
2117
2126
  }, options);
2118
2127
  }
2119
2128
  /** `[Standard]` Creates a mapped type where all properties are Optional */
@@ -2129,17 +2138,17 @@ class StandardTypeBuilder extends TypeBuilder {
2129
2138
  Pick(schema, unresolved, options = {}) {
2130
2139
  const keys = KeyArrayResolver.Resolve(unresolved);
2131
2140
  // prettier-ignore
2132
- return ObjectMap.Map(TypeClone.Clone(schema, {}), (schema) => {
2133
- if (schema.required) {
2134
- schema.required = schema.required.filter((key) => keys.includes(key));
2135
- if (schema.required.length === 0)
2136
- delete schema.required;
2141
+ return ObjectMap.Map(TypeClone.Clone(schema), (object) => {
2142
+ if (ValueGuard.IsArray(object.required)) {
2143
+ object.required = object.required.filter((key) => keys.includes(key));
2144
+ if (object.required.length === 0)
2145
+ delete object.required;
2137
2146
  }
2138
- for (const key of Object.getOwnPropertyNames(schema.properties)) {
2147
+ for (const key of Object.getOwnPropertyNames(object.properties)) {
2139
2148
  if (!keys.includes(key))
2140
- delete schema.properties[key];
2149
+ delete object.properties[key];
2141
2150
  }
2142
- return this.Create(schema);
2151
+ return this.Create(object);
2143
2152
  }, options);
2144
2153
  }
2145
2154
  /** `[Standard]` Creates a Record type */
@@ -2148,13 +2157,13 @@ class StandardTypeBuilder extends TypeBuilder {
2148
2157
  const expression = TemplateLiteralParser.ParseExact(key.pattern);
2149
2158
  // prettier-ignore
2150
2159
  return TemplateLiteralFinite.Check(expression)
2151
- ? (this.Object([...TemplateLiteralGenerator.Generate(expression)].reduce((acc, key) => ({ ...acc, [key]: TypeClone.Clone(schema, {}) }), {}), options))
2152
- : this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [key.pattern]: TypeClone.Clone(schema, {}) } });
2160
+ ? (this.Object([...TemplateLiteralGenerator.Generate(expression)].reduce((acc, key) => ({ ...acc, [key]: TypeClone.Clone(schema) }), {}), options))
2161
+ : this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [key.pattern]: TypeClone.Clone(schema) } });
2153
2162
  }
2154
2163
  else if (TypeGuard.TUnion(key)) {
2155
2164
  const union = UnionResolver.Resolve(key);
2156
2165
  if (TypeGuard.TUnionLiteral(union)) {
2157
- const properties = union.anyOf.reduce((acc, literal) => ({ ...acc, [literal.const]: TypeClone.Clone(schema, {}) }), {});
2166
+ const properties = union.anyOf.reduce((acc, literal) => ({ ...acc, [literal.const]: TypeClone.Clone(schema) }), {});
2158
2167
  return this.Object(properties, { ...options, [exports.Hint]: 'Record' });
2159
2168
  }
2160
2169
  else
@@ -2162,17 +2171,17 @@ class StandardTypeBuilder extends TypeBuilder {
2162
2171
  }
2163
2172
  else if (TypeGuard.TLiteral(key)) {
2164
2173
  if (ValueGuard.IsString(key.const) || ValueGuard.IsNumber(key.const)) {
2165
- return this.Object({ [key.const]: TypeClone.Clone(schema, {}) }, options);
2174
+ return this.Object({ [key.const]: TypeClone.Clone(schema) }, options);
2166
2175
  }
2167
2176
  else
2168
2177
  throw Error('StandardTypeBuilder: Record key of type literal is not of type string or number');
2169
2178
  }
2170
2179
  else if (TypeGuard.TInteger(key) || TypeGuard.TNumber(key)) {
2171
- return this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [exports.PatternNumberExact]: TypeClone.Clone(schema, {}) } });
2180
+ return this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [exports.PatternNumberExact]: TypeClone.Clone(schema) } });
2172
2181
  }
2173
2182
  else if (TypeGuard.TString(key)) {
2174
2183
  const pattern = ValueGuard.IsUndefined(key.pattern) ? exports.PatternStringExact : key.pattern;
2175
- return this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [pattern]: TypeClone.Clone(schema, {}) } });
2184
+ return this.Create({ ...options, [exports.Kind]: 'Record', type: 'object', patternProperties: { [pattern]: TypeClone.Clone(schema) } });
2176
2185
  }
2177
2186
  else {
2178
2187
  throw Error(`StandardTypeBuilder: Record key is an invalid type`);
@@ -2209,10 +2218,10 @@ class StandardTypeBuilder extends TypeBuilder {
2209
2218
  if (TypeGuard.TTuple(schema)) {
2210
2219
  if (ValueGuard.IsUndefined(schema.items))
2211
2220
  return [];
2212
- return schema.items.map((schema) => TypeClone.Clone(schema, {}));
2221
+ return schema.items.map((schema) => TypeClone.Clone(schema));
2213
2222
  }
2214
2223
  else {
2215
- return [TypeClone.Clone(schema, {})];
2224
+ return [TypeClone.Clone(schema)];
2216
2225
  }
2217
2226
  }
2218
2227
  /** `[Standard]` Creates a String type */
@@ -2230,13 +2239,18 @@ class StandardTypeBuilder extends TypeBuilder {
2230
2239
  /** `[Standard]` Creates a Tuple type */
2231
2240
  Tuple(items, options = {}) {
2232
2241
  const [additionalItems, minItems, maxItems] = [false, items.length, items.length];
2233
- const clonedItems = items.map((item) => TypeClone.Clone(item, {}));
2242
+ const clonedItems = items.map((item) => TypeClone.Clone(item));
2234
2243
  // prettier-ignore
2235
2244
  const schema = (items.length > 0 ?
2236
2245
  { ...options, [exports.Kind]: 'Tuple', type: 'array', items: clonedItems, additionalItems, minItems, maxItems } :
2237
2246
  { ...options, [exports.Kind]: 'Tuple', type: 'array', minItems, maxItems });
2238
2247
  return this.Create(schema);
2239
2248
  }
2249
+ /** `[Standard]` Maps a literal strings first character to lowercase */
2250
+ Uncapitalize(schema, options = {}) {
2251
+ const [first, rest] = [schema.const.slice(0, 1), schema.const.slice(1)];
2252
+ return exports.Type.Literal(`${first.toLocaleLowerCase()}${rest}`, options);
2253
+ }
2240
2254
  Union(union, options = {}) {
2241
2255
  if (TypeGuard.TTemplateLiteral(union)) {
2242
2256
  return TemplateLiteralResolver.Resolve(union);
@@ -2247,7 +2261,7 @@ class StandardTypeBuilder extends TypeBuilder {
2247
2261
  return this.Never(options);
2248
2262
  if (anyOf.length === 1)
2249
2263
  return this.Create(TypeClone.Clone(anyOf[0], options));
2250
- const clonedAnyOf = anyOf.map((schema) => TypeClone.Clone(schema, {}));
2264
+ const clonedAnyOf = anyOf.map((schema) => TypeClone.Clone(schema));
2251
2265
  return this.Create({ ...options, [exports.Kind]: 'Union', anyOf: clonedAnyOf });
2252
2266
  }
2253
2267
  }
@@ -2259,6 +2273,10 @@ class StandardTypeBuilder extends TypeBuilder {
2259
2273
  Unsafe(options = {}) {
2260
2274
  return this.Create({ ...options, [exports.Kind]: options[exports.Kind] || 'Unsafe' });
2261
2275
  }
2276
+ /** `[Standard]` Maps a literal string to uppercase */
2277
+ Uppercase(schema, options = {}) {
2278
+ return exports.Type.Literal(schema.const.toUpperCase(), options);
2279
+ }
2262
2280
  }
2263
2281
  exports.StandardTypeBuilder = StandardTypeBuilder;
2264
2282
  // --------------------------------------------------------------------------
@@ -2267,7 +2285,21 @@ exports.StandardTypeBuilder = StandardTypeBuilder;
2267
2285
  class ExtendedTypeBuilder extends StandardTypeBuilder {
2268
2286
  /** `[Extended]` Creates a AsyncIterator type */
2269
2287
  AsyncIterator(items, options = {}) {
2270
- return this.Create({ ...options, [exports.Kind]: 'AsyncIterator', type: 'AsyncIterator', items: TypeClone.Clone(items, {}) });
2288
+ return this.Create({ ...options, [exports.Kind]: 'AsyncIterator', type: 'AsyncIterator', items: TypeClone.Clone(items) });
2289
+ }
2290
+ /** `[Extended]` Recursively unwraps Promise from the given type. */
2291
+ Awaited(schema, options = {}) {
2292
+ const AwaitedRest = (rest) => {
2293
+ if (rest.length === 0)
2294
+ return rest;
2295
+ const [L, ...R] = rest;
2296
+ return [this.Awaited(L), ...AwaitedRest(R)];
2297
+ };
2298
+ // prettier-ignore
2299
+ return (TypeGuard.TIntersect(schema) ? exports.Type.Intersect(AwaitedRest(schema.allOf)) :
2300
+ TypeGuard.TUnion(schema) ? exports.Type.Union(AwaitedRest(schema.anyOf)) :
2301
+ TypeGuard.TPromise(schema) ? this.Awaited(schema.item) :
2302
+ TypeClone.Clone(schema, options));
2271
2303
  }
2272
2304
  /** `[Extended]` Creates a BigInt type */
2273
2305
  BigInt(options = {}) {
@@ -2279,8 +2311,8 @@ class ExtendedTypeBuilder extends StandardTypeBuilder {
2279
2311
  }
2280
2312
  /** `[Extended]` Creates a Constructor type */
2281
2313
  Constructor(parameters, returns, options) {
2282
- const clonedReturns = TypeClone.Clone(returns, {});
2283
- const clonedParameters = parameters.map((parameter) => TypeClone.Clone(parameter, {}));
2314
+ const clonedReturns = TypeClone.Clone(returns);
2315
+ const clonedParameters = parameters.map((parameter) => TypeClone.Clone(parameter));
2284
2316
  return this.Create({ ...options, [exports.Kind]: 'Constructor', type: 'constructor', parameters: clonedParameters, returns: clonedReturns });
2285
2317
  }
2286
2318
  /** `[Extended]` Creates a Date type */
@@ -2290,7 +2322,7 @@ class ExtendedTypeBuilder extends StandardTypeBuilder {
2290
2322
  /** `[Extended]` Creates a Function type */
2291
2323
  Function(parameters, returns, options) {
2292
2324
  const clonedReturns = TypeClone.Clone(returns, {});
2293
- const clonedParameters = parameters.map((parameter) => TypeClone.Clone(parameter, {}));
2325
+ const clonedParameters = parameters.map((parameter) => TypeClone.Clone(parameter));
2294
2326
  return this.Create({ ...options, [exports.Kind]: 'Function', type: 'function', parameters: clonedParameters, returns: clonedReturns });
2295
2327
  }
2296
2328
  /** `[Extended]` Extracts the InstanceType from the given Constructor */
@@ -2299,7 +2331,7 @@ class ExtendedTypeBuilder extends StandardTypeBuilder {
2299
2331
  }
2300
2332
  /** `[Extended]` Creates an Iterator type */
2301
2333
  Iterator(items, options = {}) {
2302
- return this.Create({ ...options, [exports.Kind]: 'Iterator', type: 'Iterator', items: TypeClone.Clone(items, {}) });
2334
+ return this.Create({ ...options, [exports.Kind]: 'Iterator', type: 'Iterator', items: TypeClone.Clone(items) });
2303
2335
  }
2304
2336
  /** `[Extended]` Extracts the Parameters from the given Function type */
2305
2337
  Parameters(schema, options = {}) {
@@ -2307,7 +2339,7 @@ class ExtendedTypeBuilder extends StandardTypeBuilder {
2307
2339
  }
2308
2340
  /** `[Extended]` Creates a Promise type */
2309
2341
  Promise(item, options = {}) {
2310
- return this.Create({ ...options, [exports.Kind]: 'Promise', type: 'Promise', item: TypeClone.Clone(item, {}) });
2342
+ return this.Create({ ...options, [exports.Kind]: 'Promise', type: 'Promise', item: TypeClone.Clone(item) });
2311
2343
  }
2312
2344
  /** `[Extended]` Creates a String pattern type from Regular Expression */
2313
2345
  RegExp(unresolved, options = {}) {
package/value/convert.js CHANGED
@@ -280,7 +280,7 @@ function TUnknown(schema, references, value) {
280
280
  function TVoid(schema, references, value) {
281
281
  return value;
282
282
  }
283
- function TUserDefined(schema, references, value) {
283
+ function TKind(schema, references, value) {
284
284
  return value;
285
285
  }
286
286
  function Visit(schema, references, value) {
@@ -348,7 +348,7 @@ function Visit(schema, references, value) {
348
348
  default:
349
349
  if (!Types.TypeRegistry.Has(schema_[Types.Kind]))
350
350
  throw new ValueConvertUnknownTypeError(schema_);
351
- return TUserDefined(schema_, references_, value);
351
+ return TKind(schema_, references_, value);
352
352
  }
353
353
  }
354
354
  /** Converts any type mismatched values to their target type if a reasonable conversion is possible. */