From b095510e24e77f295cad5401e6cf77108f42e233 Mon Sep 17 00:00:00 2001 From: sinclair Date: Sat, 25 Nov 2023 14:30:06 +0900 Subject: [PATCH] Reimplement Index Types --- examples/index.ts | 11 +- examples/next/indexer.ts | 2 +- src/typebox.ts | 699 ++++++++++++++++++++------------------- src/value/transform.ts | 12 +- 4 files changed, 375 insertions(+), 349 deletions(-) diff --git a/examples/index.ts b/examples/index.ts index bd9b54ab1..675955697 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -41,17 +41,18 @@ import { IsTemplateLiteralFiniteCheck, UnionToTuple, PatternNumber, - Increment, - AccessResolver, + Counter, + IndexAccessResolver, IndexResolver, Assert, UnionToIntersect, KeyResolver, Ensure, + KeyOfResolver, } from '@sinclair/typebox' -const A = Type.KeyOf(Type.Tuple([Type.Number()])) -console.log(A) +const R = KeyOfResolver.Resolve(Type.Union([Type.Object({ x: Type.Number(), y: Type.Number() }), Type.Object({ x: Type.Number(), z: Type.Number() })])) +const T = Type.Union([Type.Object({ x: Type.Number() }), Type.Object({ z: Type.Number() })]) -const M = KeyResolver.Resolve(Type.Tuple([Type.Number(), Type.Number(), Type.Number()])) +const K = Type.KeyOf(T) diff --git a/examples/next/indexer.ts b/examples/next/indexer.ts index 6fc5bfa81..715f19fce 100644 --- a/examples/next/indexer.ts +++ b/examples/next/indexer.ts @@ -1,7 +1,7 @@ import { TypeSystem } from '@sinclair/typebox/system' import { TypeCompiler } from '@sinclair/typebox/compiler' import { Value, ValuePointer } from '@sinclair/typebox/value' -import { Type, AccessResolver, TemplateLiteralParser, TemplateLiteralFinite, TemplateLiteralResolver, TypeGuard, TIntersect, TUnion, TTemplateLiteral, IsTemplateLiteralFiniteCheck, UnionToTuple, Static, TSchema, TLiteralValue, TLiteral, TNumber, TInteger, TBigInt, TString, PatternNumber } from '@sinclair/typebox' +import { Type, IndexAccessResolver, TemplateLiteralParser, TemplateLiteralFinite, TemplateLiteralResolver, TypeGuard, TIntersect, TUnion, TTemplateLiteral, IsTemplateLiteralFiniteCheck, UnionToTuple, Static, TSchema, TLiteralValue, TLiteral, TNumber, TInteger, TBigInt, TString, PatternNumber } from '@sinclair/typebox' import { TObject } from '@sinclair/typebox' const A = Type.Index(Type.Object({ diff --git a/src/typebox.ts b/src/typebox.ts index f8baaa8d3..8c64bfebe 100644 --- a/src/typebox.ts +++ b/src/typebox.ts @@ -26,32 +26,32 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // Symbols -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export const Transform = Symbol.for('TypeBox.Transform') export const Readonly = Symbol.for('TypeBox.Readonly') export const Optional = Symbol.for('TypeBox.Optional') export const Hint = Symbol.for('TypeBox.Hint') export const Kind = Symbol.for('TypeBox.Kind') -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // Patterns -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export const PatternBoolean = '(true|false)' export const PatternNumber = '(0|[1-9][0-9]*)' export const PatternString = '(.*)' export const PatternBooleanExact = `^${PatternBoolean}$` export const PatternNumberExact = `^${PatternNumber}$` export const PatternStringExact = `^${PatternString}$` -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // Into -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export function Into(func: () => U): U { return func() } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // Helpers -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TupleToIntersect = T extends [infer I] ? I : T extends [infer I, ...infer R] ? I & TupleToIntersect : never export type TupleToUnion = { [K in keyof T]: T[K] }[number] export type UnionToIntersect = (U extends unknown ? (arg: U) => 0 : never) extends (arg: infer I) => 0 ? I : never @@ -63,21 +63,21 @@ export type Assert = T extends E ? T : never export type Evaluate = T extends infer O ? { [K in keyof O]: O[K] } : never export type Ensure = T extends infer U ? U : never export type EmptyString = '' -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // Type Asserts -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type AssertProperties = T extends TProperties ? T : TProperties export type AssertRest = T extends E ? T : [] export type AssertType = T extends E ? T : TNever -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // Modifiers -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TReadonlyOptional = TOptional & TReadonly export type TReadonly = T & { [Readonly]: 'Readonly' } export type TOptional = T & { [Optional]: 'Optional' } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TSchema -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface SchemaOptions { $schema?: string /** Id for this schema */ @@ -106,9 +106,9 @@ export interface TSchema extends SchemaOptions, TKind { params: unknown[] static: unknown } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TAnySchema -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TAnySchema = | TSchema | TAny @@ -141,9 +141,9 @@ export type TAnySchema = | TUint8Array | TUnknown | TVoid -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TNumeric -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface NumericOptions extends SchemaOptions { exclusiveMaximum?: N exclusiveMinimum?: N @@ -151,16 +151,16 @@ export interface NumericOptions extends SchemaOptions minimum?: N multipleOf?: N } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TAny -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TAny extends TSchema { [Kind]: 'Any' static: any } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TArray -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface ArrayOptions extends SchemaOptions { /** The minimum number of items in this array */ minItems?: number @@ -181,18 +181,18 @@ export interface TArray extends TSchema, ArrayOptio type: 'array' items: T } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TAsyncIterator -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TAsyncIterator extends TSchema { [Kind]: 'AsyncIterator' static: AsyncIterableIterator> type: 'AsyncIterator' items: T } -// ------------------------------------------------------------------------------- +// ----------------------------------------------------------------------- // TAwaited -// ------------------------------------------------------------------------------- +// ----------------------------------------------------------------------- // prettier-ignore export type TAwaitedRest = T extends [infer L extends TSchema, ...infer R extends TSchema[]] @@ -204,33 +204,33 @@ export type TAwaited = T extends TUnion ? TUnion> : T extends TPromise ? TAwaited : T -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TBigInt -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TBigInt extends TSchema, NumericOptions { [Kind]: 'BigInt' static: bigint type: 'bigint' } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TBoolean -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TBoolean extends TSchema { [Kind]: 'Boolean' static: boolean type: 'boolean' } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TConstructorParameters -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TConstructorParameters> = Ensure> -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TInstanceType -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TInstanceType> = T['returns'] -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TComposite -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // prettier-ignore export type TCompositeKeys = T extends [infer L extends TObject, ...infer R extends TObject[]] @@ -249,9 +249,9 @@ export type TCompositeReduce = UnionToTuple = TIntersect extends TIntersect ? TObject> : TObject<{}> -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TConstructor -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TConstructorReturnTypeResolve = Static export type TConstructorParametersResolve = T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? [Static, ...TFunctionParametersResolve] : [] export type TConstructorResolve = Ensure) => TConstructorReturnTypeResolve> @@ -262,9 +262,9 @@ export interface TConstructor export type TEnumValue = string | number export type TEnumKey = string @@ -294,9 +294,9 @@ export interface TEnum = Record[] } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TExtends -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // prettier-ignore export type TExtends = (Static extends Static ? T : U) extends infer O extends TSchema ? @@ -304,9 +304,9 @@ export type TExtends : O : never -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TExclude -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TExcludeTemplateLiteralResult = UnionType.Resolve }[T]>>> export type TExcludeTemplateLiteral = Exclude, Static> extends infer S ? TExcludeTemplateLiteralResult> : never // prettier-ignore @@ -318,9 +318,9 @@ export type TExclude = T extends TTemplateLiteral ? TExcludeTemplateLiteral : T extends TUnion ? TExcludeArray : T extends U ? TNever : T -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TExtract -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TExtractTemplateLiteralResult = UnionType.Resolve }[T]>>> export type TExtractTemplateLiteral = Extract, Static> extends infer S ? TExtractTemplateLiteralResult> : never // prettier-ignore @@ -332,9 +332,9 @@ export type TExtract = T extends TTemplateLiteral ? TExtractTemplateLiteral : T extends TUnion ? TExtractArray : T extends U ? T : T -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TFunction -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TFunctionReturnTypeResolve = Static export type TFunctionParametersResolve = T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? [Static, ...TFunctionParametersResolve] : [] export type TFunctionResolve = Ensure<(...param: TFunctionParametersResolve) => TFunctionReturnTypeResolve> @@ -345,9 +345,9 @@ export interface TFunction> = F extends true ? UnionToTuple> : [] export type TIndexerUnion = T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? [...TIndexer, ...TIndexerUnion] : [] export type TIndexerLiteral = T extends PropertyKey ? [T] : [] @@ -392,9 +392,9 @@ export type TIndexKeys = : [] export type TIndex = UnionType.Resolve> -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TIntrinsic -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TIntrinsicMode = 'Uppercase' | 'Lowercase' | 'Capitalize' | 'Uncapitalize' // prettier-ignore export type TIntrinsicTemplateLiteral = @@ -427,17 +427,17 @@ export type TIntrinsic = T extends TUnion ? TUnion> : T extends TLiteral ? TLiteral> : T -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TInteger -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TInteger extends TSchema, NumericOptions { [Kind]: 'Integer' static: number type: 'integer' } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TIntersect -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TUnevaluatedProperties = undefined | TSchema | boolean export interface IntersectOptions extends SchemaOptions { unevaluatedProperties?: TUnevaluatedProperties @@ -448,22 +448,22 @@ export interface TIntersect extends TSchema, In type?: 'object' allOf: [...T] } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TIterator -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TIterator extends TSchema { [Kind]: 'Iterator' static: IterableIterator> type: 'Iterator' items: T } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TKeyOf -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TLiteral -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TLiteralValue = boolean | number | string // | bigint - supported but variant disable due to potential numeric type conflicts export type TLiteralBoolean = TLiteral export type TLiteralNumber = TLiteral @@ -473,41 +473,41 @@ export interface TLiteral extends TSche static: T const: T } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TNever -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TNever extends TSchema { [Kind]: 'Never' static: never not: {} } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TNot -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TNot extends TSchema { [Kind]: 'Not' static: T extends TNot ? Static : unknown not: T } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TNull -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TNull extends TSchema { [Kind]: 'Null' static: null type: 'null' } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TNumber -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TNumber extends TSchema, NumericOptions { [Kind]: 'Number' static: number type: 'number' } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TObject -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type ReadonlyOptionalPropertyKeys = { [K in keyof T]: T[K] extends TReadonly ? (T[K] extends TOptional ? K : never) : never }[keyof T] export type ReadonlyPropertyKeys = { [K in keyof T]: T[K] extends TReadonly ? (T[K] extends TOptional ? never : K) : never }[keyof T] export type OptionalPropertyKeys = { [K in keyof T]: T[K] extends TOptional ? (T[K] extends TReadonly ? never : K) : never }[keyof T] @@ -544,9 +544,9 @@ export interface TObject extends TSchema, O properties: T required?: string[] } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TOmit -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TOmitProperties = Evaluate>> export type TOmitRest = AssertRest<{ [K2 in keyof T]: TOmit, K> }> // prettier-ignore @@ -556,13 +556,13 @@ export type TOmit T extends TUnion ? TUnion> : T extends TObject ? TObject> : T -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TParameters -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TParameters = Ensure> -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TPartial -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TPartialObjectArray = AssertRest<{ [K in keyof T]: TPartial> }, TObject[]> export type TPartialRest = AssertRest<{ [K in keyof T]: TPartial> }> // prettier-ignore @@ -580,9 +580,9 @@ export type TPartial = T extends TUnion ? TUnion> : T extends TObject ? TObject> : T -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TPick -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // Note the key K will overlap for varying TProperties gathered via recursive union and intersect traversal. Because of this, // we need to extract only keys assignable to T on K2. This behavior is only required for Pick only. // prettier-ignore @@ -598,18 +598,18 @@ export type TPick T extends TUnion ? TUnion> : T extends TObject ? TObject> : T -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TPromise -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TPromise extends TSchema { [Kind]: 'Promise' static: Promise> type: 'Promise' item: TSchema } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TRecord -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TRecordFromUnionLiteralString = { [_ in K['const']]: T } export type TRecordFromUnionLiteralNumber = { [_ in K['const']]: T } // prettier-ignore @@ -650,9 +650,9 @@ export interface TRecord extends TSchema { [Hint]: 'Recursive' static: TRecursiveReduce } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TRef -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TRef extends TSchema { [Kind]: 'Ref' static: Static $ref: string } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TRest -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TRest = T extends TIntersect ? R : T extends TUnion ? R : T extends TTuple ? R : [] -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TReturnType -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TReturnType = T['returns'] -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TRequired -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TRequiredRest = AssertRest<{ [K in keyof T]: TRequired> }> // prettier-ignore export type TRequiredProperties = Evaluate = T extends TUnion ? TUnion> : T extends TObject ? TObject> : T -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TString -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type StringFormatOption = | 'date-time' | 'time' @@ -748,9 +748,9 @@ export interface TString extends TSchema, StringOptions { static: string type: 'string' } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TSymbol -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type SymbolValue = string | number | undefined export interface TSymbol extends TSchema, SchemaOptions { [Kind]: 'Symbol' @@ -780,9 +780,9 @@ export type TTemplateLiteralDslParserTemplate = T extends `${infer L}` ? [TLiteral] : [] export type TTemplateLiteralDslParser = Ensure, TTemplateLiteralKind[]>>> -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TTemplateLiteral -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // prettier-ignore export type IsTemplateLiteralFiniteCheck = T extends TTemplateLiteral ? IsTemplateLiteralFiniteArray> : @@ -821,9 +821,9 @@ export interface TTemplateLiteral = { [K in keyof T]: DecodeType @@ -865,9 +865,9 @@ export interface TTransform [key: string]: any } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TTuple -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TTupleRest = T extends [infer L, ...infer R] ? [Static, P>, ...TTupleRest, P>] : [] export interface TTuple extends TSchema { [Kind]: 'Tuple' @@ -878,17 +878,17 @@ export interface TTuple extends TSchema { minItems: number maxItems: number } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TUndefined -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TUndefined extends TSchema { [Kind]: 'Undefined' static: undefined type: 'undefined' } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TUnionLiteral -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // prettier-ignore export type TLiteralUnionReduce[]> = T extends [infer L, ...infer R] ? [Assert>['const'], ...TLiteralUnionReduce[]>>] : @@ -897,9 +897,9 @@ export type TLiteralUnionReduce[]> = export type TUnionLiteralKeyRest[]>> = T extends TUnion ? TLiteralUnionReduce[]>> : [] -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TUnion -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // prettier-ignore export type TUnionTemplateLiteral> = Ensure }[S]>, TLiteral[]>>> export interface TUnion extends TSchema { @@ -907,9 +907,9 @@ export interface TUnion extends TSchema { static: { [K in keyof T]: T[K] extends TSchema ? Static : never }[number] anyOf: T } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TUint8Array -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface Uint8ArrayOptions extends SchemaOptions { maxByteLength?: number minByteLength?: number @@ -919,16 +919,16 @@ export interface TUint8Array extends TSchema, Uint8ArrayOptions { static: Uint8Array type: 'uint8array' } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TUnknown -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TUnknown extends TSchema { [Kind]: 'Unknown' static: unknown } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TUnsafe -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface UnsafeOptions extends SchemaOptions { [Kind]?: string } @@ -936,26 +936,26 @@ export interface TUnsafe extends TSchema { [Kind]: string static: T } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TVoid -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export interface TVoid extends TSchema { [Kind]: 'Void' static: void type: 'void' } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // Static -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ /** Creates an decoded static type from a TypeBox type */ export type StaticDecode = Static, P> /** Creates an encoded static type from a TypeBox type */ export type StaticEncode = Static /** Creates a static type from a TypeBox type */ export type Static = (T & { params: P })['static'] -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TypeRegistry -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type TypeRegistryValidationFunction = (schema: TSchema, value: unknown) => boolean /** A registry for user defined types */ export namespace TypeRegistry { @@ -985,17 +985,17 @@ export namespace TypeRegistry { return map.get(kind) } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TypeBoxError -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export class TypeBoxError extends Error { constructor(message: string) { super(message) } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TypeRegistry -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export type FormatRegistryValidationFunction = (value: string) => boolean /** A registry for user defined string formats */ export namespace FormatRegistry { @@ -1038,9 +1038,9 @@ export namespace Discard { return keys.reduce((acc, key) => Key(acc, key), value) } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // ValueGuard -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ /** Provides functions to type guard raw JavaScript values */ export namespace ValueGuard { /** Returns true if this value is an array */ @@ -1084,9 +1084,9 @@ export namespace ValueGuard { return value === undefined } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TypeGuard -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export class TypeGuardUnknownTypeError extends TypeBoxError {} /** Provides functions to test if JavaScript values are TypeBox types */ export namespace TypeGuard { @@ -1772,9 +1772,9 @@ export namespace UnionType { ) as Resolve } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // ExtendsUndefined -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ /** Fast undefined check used for properties of type undefined */ export namespace ExtendsUndefined { export function TIntersect(schema: TIntersect) { @@ -1797,9 +1797,9 @@ export namespace ExtendsUndefined { ) } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TypeExtends -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export class TypeExtendsError extends TypeBoxError {} export enum TypeExtendsResult { Union, @@ -1808,21 +1808,21 @@ export enum TypeExtendsResult { } // prettier-ignore export namespace TypeExtends { - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // IntoBooleanResult - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function IntoBooleanResult(result: TypeExtendsResult) { return result === TypeExtendsResult.False ? result : TypeExtendsResult.True } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Throw - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function Throw(message: string): never { throw new TypeExtendsError(message) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // StructuralRight - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function IsStructuralRight(right: TSchema): boolean { return ( TypeGuard.TNever(right) || @@ -1842,9 +1842,9 @@ export namespace TypeExtends { Throw('StructuralRight') ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Any - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TAnyRight(left: TSchema, right: TAny) { return TypeExtendsResult.True } @@ -1858,9 +1858,9 @@ export namespace TypeExtends { TypeExtendsResult.Union ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Array - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TArrayRight(left: TSchema, right: TArray) { return ( TypeGuard.TUnknown(left) ? TypeExtendsResult.False : @@ -1877,9 +1877,9 @@ export namespace TypeExtends { IntoBooleanResult(Visit(left.items, right.items)) ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // AsyncIterator - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TAsyncIterator(left: TAsyncIterator, right: TSchema) { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -1887,9 +1887,9 @@ export namespace TypeExtends { IntoBooleanResult(Visit(left.items, right.items)) ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // BigInt - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TBigInt(left: TBigInt, right: TSchema): TypeExtendsResult { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -1899,9 +1899,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Boolean - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TBooleanRight(left: TSchema, right: TBoolean) { return ( TypeGuard.TLiteralBoolean(left) ? TypeExtendsResult.True : @@ -1918,9 +1918,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Constructor - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TConstructor(left: TConstructor, right: TSchema) { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -1931,9 +1931,9 @@ export namespace TypeExtends { IntoBooleanResult(Visit(left.returns, right.returns)) ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Date - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TDate(left: TDate, right: TSchema) { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -1943,9 +1943,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Function - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TFunction(left: TFunction, right: TSchema) { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -1956,9 +1956,9 @@ export namespace TypeExtends { IntoBooleanResult(Visit(left.returns, right.returns)) ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Integer - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TIntegerRight(left: TSchema, right: TInteger) { return ( TypeGuard.TLiteral(left) && ValueGuard.IsNumber(left.const) ? TypeExtendsResult.True : @@ -1975,9 +1975,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Intersect - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TIntersectRight(left: TSchema, right: TIntersect): TypeExtendsResult { return right.allOf.every((schema) => Visit(left, schema) === TypeExtendsResult.True) ? TypeExtendsResult.True @@ -1988,9 +1988,9 @@ export namespace TypeExtends { ? TypeExtendsResult.True : TypeExtendsResult.False } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Iterator - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TIterator(left: TIterator, right: TSchema) { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -1998,9 +1998,9 @@ export namespace TypeExtends { IntoBooleanResult(Visit(left.items, right.items)) ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Literal - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TLiteral(left: TLiteral, right: TSchema): TypeExtendsResult { return ( TypeGuard.TLiteral(right) && right.const === left.const ? TypeExtendsResult.True : @@ -2014,18 +2014,18 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Never - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TNeverRight(left: TSchema, right: TNever) { return TypeExtendsResult.False } function TNever(left: TNever, right: TSchema) { return TypeExtendsResult.True } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Not - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function UnwrapTNot(schema: T): TUnknown | TNot['not'] { let [current, depth]: [TSchema, number] = [schema, 0] while (true) { @@ -2046,9 +2046,9 @@ export namespace TypeExtends { Throw('Invalid fallthrough for Not') ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Null - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TNull(left: TNull, right: TSchema) { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -2058,9 +2058,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Number - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TNumberRight(left: TSchema, right: TNumber) { return ( TypeGuard.TLiteralNumber(left) ? TypeExtendsResult.True : @@ -2077,9 +2077,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Object - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function IsObjectPropertyCount(schema: TObject, count: number) { return Object.getOwnPropertyNames(schema.properties).length === count } @@ -2127,9 +2127,9 @@ export namespace TypeExtends { const then = Type.Function([Type.Any()], Type.Any()) return IsObjectPropertyCount(schema, 0) || (IsObjectPropertyCount(schema, 1) && 'then' in schema.properties && IntoBooleanResult(Visit(schema.properties['then'], then)) === TypeExtendsResult.True) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Property - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function Property(left: TSchema, right: TSchema) { return ( Visit(left, right) === TypeExtendsResult.False ? TypeExtendsResult.False : @@ -2189,9 +2189,9 @@ export namespace TypeExtends { })() ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Promise - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TPromise(left: TPromise, right: TSchema) { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -2200,9 +2200,9 @@ export namespace TypeExtends { IntoBooleanResult(Visit(left.item, right.item)) ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Record - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function RecordKey(schema: TRecord) { return ( PatternNumberExact in schema.patternProperties ? Type.Number() : @@ -2243,9 +2243,9 @@ export namespace TypeExtends { Visit(RecordValue(left), RecordValue(right)) ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // String - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TStringRight(left: TSchema, right: TString) { return ( TypeGuard.TLiteral(left) && ValueGuard.IsString(left.const) ? TypeExtendsResult.True : @@ -2262,9 +2262,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Symbol - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TSymbol(left: TSymbol, right: TSchema): TypeExtendsResult { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -2274,9 +2274,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // TemplateLiteral - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TTemplateLiteral(left: TSchema, right: TSchema) { // TemplateLiteral types are resolved to either unions for finite expressions or string // for infinite expressions. Here we call to TemplateLiteralResolver to resolve for @@ -2287,9 +2287,9 @@ export namespace TypeExtends { Throw('Invalid fallthrough for TemplateLiteral') ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Tuple - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function IsArrayOfTuple(left: TTuple, right: TSchema) { return ( TypeGuard.TArray(right) && @@ -2317,9 +2317,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Uint8Array - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TUint8Array(left: TUint8Array, right: TSchema) { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -2329,9 +2329,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Undefined - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TUndefined(left: TUndefined, right: TSchema) { return ( IsStructuralRight(right) ? StructuralRight(left, right) : @@ -2342,9 +2342,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Union - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TUnionRight(left: TSchema, right: TUnion): TypeExtendsResult { return right.anyOf.some((schema) => Visit(left, schema) === TypeExtendsResult.True) ? TypeExtendsResult.True @@ -2355,9 +2355,9 @@ export namespace TypeExtends { ? TypeExtendsResult.True : TypeExtendsResult.False } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Unknown - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function TUnknownRight(left: TSchema, right: TUnknown) { return TypeExtendsResult.True } @@ -2378,9 +2378,9 @@ export namespace TypeExtends { TypeExtendsResult.False ) } - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ // Void - // -------------------------------------------------------------------------- + // ------------------------------------------------------------------ function VoidRight(left: TSchema, right: TVoid) { return ( TypeGuard.TUndefined(left) ? TypeExtendsResult.True : @@ -2438,9 +2438,10 @@ export namespace TypeExtends { return Visit(left, right) } } -// -------------------------------------------------------------------------- + +// ------------------------------------------------------------------ // Clone -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export namespace Clone { function ArrayType(value: unknown[]) { return (value as any).map((value: unknown) => Visit(value as any)) @@ -2471,9 +2472,9 @@ export namespace Clone { return Visit(value) } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TypeClone -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ /** Specialized Clone for Types */ export namespace TypeClone { /** Clones a Rest */ @@ -2485,9 +2486,9 @@ export namespace TypeClone { return { ...Clone.Value(schema), ...options } } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // Intrinsic -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // prettier-ignore export namespace Intrinsic { function Uncapitalize(value: string): string { @@ -2545,9 +2546,9 @@ export namespace Intrinsic { return Visit(schema, mode) } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // ObjectMap -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // prettier-ignore export namespace ObjectMap { function TIntersect(schema: TIntersect, callback: (object: TObject) => TObject) { @@ -2575,160 +2576,183 @@ export namespace ObjectMap { return { ...Visit(TypeClone.Type(schema), callback), ...options } as unknown as T } } -// ---------------------------------------------------------------- -// Increment -// ---------------------------------------------------------------- -// prettier-ignore -export namespace Increment { - export type Next = Reverse, B>> - export type Base = { m: '9', t: '01', '0': '1', '1': '2', '2': '3', '3': '4', '4': '5', '5': '6', '6': '7', '7': '8', '8': '9', '9': '0' } - export type Reverse = T extends `${infer L}${infer R}` ? `${Reverse}${L}` : T - export type Tick = B[Assert] - export type Increment = T extends B['m'] ? B['t'] : T extends `${infer L}${infer R}` ? L extends B['m'] - ? `${Assert, string>}${Increment}` - : `${Assert, string>}${R}` - : never +// ------------------------------------------------------------------ +// Counter +// ------------------------------------------------------------------ +export namespace Counter { + export type ReverseString = T extends `${infer L}${infer R}` ? `${ReverseString}${L}` : T + export type Base = { m: '9'; t: '01'; '0': '1'; '1': '2'; '2': '3'; '3': '4'; '4': '5'; '5': '6'; '6': '7'; '7': '8'; '8': '9'; '9': '0' } + export type Next = ReverseString, B>> + export type Tick = B[Assert] + export type Increment = T extends B['m'] ? B['t'] : T extends `${infer L}${infer R}` ? (L extends B['m'] ? `${Assert, string>}${Increment}` : `${Assert, string>}${R}`) : never } // ---------------------------------------------------------------- -// KeyResolver +// Resolver: PropertyKeys // ---------------------------------------------------------------- // prettier-ignore -export namespace KeyResolver { +export namespace PropertyKeys { // ---------------------------------------------------------------- - // Collect + // From // ---------------------------------------------------------------- - export type Collect = ( - T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? [Resolve, ...Collect] - : [] - ) - export function Collect(T: [...T]): Collect { + function TakeLeft(T: T[], A: (L: T, R: T[]) => unknown, B: () => unknown) { const [L, ...R] = T - return ( - T.length > 0 - ? [Resolve(L), ...Collect(R)] - : [] - ) as Collect + return T.length > 0 ? A(L, R) : B() } // ---------------------------------------------------------------- // Includes // ---------------------------------------------------------------- export type Includes = ( T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] - ? S extends L - ? true - : Includes + ? S extends L ? true : Includes : false ) - export function Includes(T: [...T], S: S) { - return ( - T.includes(S) + /** Returns true if this set contains the given property. */ + export function Includes(T: [...T], S: S): Includes { + return TakeLeft(T, + (L, R) => S === L ? true : Includes(R, S), + () => false ) as Includes } // ---------------------------------------------------------------- - // IntersectDistinct + // Distinct + // ---------------------------------------------------------------- + export type Distinct = + T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] + ? Includes extends false + ? Distinct + : Distinct + : Acc + /** Returns a new set containing only distinct elements */ + export function Distinct(T: [...T], Acc: PropertyKey[] = []): Distinct { + return TakeLeft(T, + (L, R) => Includes(Acc, L) === false + ? Distinct(R, [...Acc, L]) + : Distinct(R, [...Acc]), + () => Acc + ) as Distinct + } + // ---------------------------------------------------------------- + // Intersect // ---------------------------------------------------------------- - export type IntersectDistinct = ( + export type Intersect = ( T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? Includes extends true - ? [...IntersectDistinct] - : [L, ...IntersectDistinct] + ? [L, ...Intersect] + : [...Intersect] + : [] + ) + /** Returns the Intersect of the given PropertyKey sets */ + export function Intersect(T: [...T], S: [...S]): Intersect { + return TakeLeft(T, + (L, R) => Includes(S, L) === true + ? [L, ...Intersect(R, S)] + : [...Intersect(R, S)], + () => [] + ) as Intersect + } + // ---------------------------------------------------------------- + // Union + // ---------------------------------------------------------------- + export type Union = ( + T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] + ? Includes extends true + ? [...Union] + : [L, ...Union] : S ) - export function IntersectDistinct(T: [...T], S: [...S]): IntersectDistinct { - const [L, ...R] = T - return ( - T.length > 0 - ? Includes(S, L) === true - ? [...IntersectDistinct(R, S)] - : [L, ...IntersectDistinct(R, S)] - : S - ) as IntersectDistinct + /** Returns the Union of the given PropertyKey sets */ + export function Union(T: [...T], S: [...S]): Union { + return TakeLeft(T, + (L, R) => Includes(S, L) === true + ? [...Union(R, S)] + : [L, ...Union(R, S)], + () => S + ) as Union } // ---------------------------------------------------------------- - // IntersectIntersection + // IntersectMany // ---------------------------------------------------------------- - export type IntersectIntersection = ( - T extends [infer L extends PropertyKey[]] + export type IntersectMany = ( + T extends [infer L extends PropertyKey[]] ? L - : T extends [infer L extends PropertyKey[], ...infer R extends PropertyKey[][]] - ? IntersectDistinct> - : [] - ) - export function IntersectIntersection(T: [...T]): IntersectIntersection { + : T extends [infer L extends PropertyKey[], ...infer R extends PropertyKey[][]] + ? Intersect> + : [] + ) + /** Returns the Intersect of multiple PropertyKey sets */ + export function IntersectMany(T: [...T]): IntersectMany { return ( T.length === 1 ? T[0] - : Into(() => { - const [L, ...R] = T - return L.length > 0 - ? IntersectDistinct(L, IntersectIntersection(R)) - : [] - }) - ) as IntersectIntersection + : TakeLeft(T, + (L, R) => L.length > 0 ? Intersect(L, IntersectMany(R)) : [], + () => [] + ) + ) as IntersectMany } // ---------------------------------------------------------------- - // Intersect + // UnionMany // ---------------------------------------------------------------- - export type Intersect> = ( - IntersectIntersection + export type UnionMany = ( + T extends [infer L extends PropertyKey[]] + ? L + : T extends [infer L extends PropertyKey[], ...infer R extends PropertyKey[][]] + ? Union> + : [] ) - export function Intersect(T: [...T], C = Collect(T)): Intersect { - return ( - IntersectIntersection(C as PropertyKey[][]) as Intersect - ) + /** Returns the Union of multiple PropertyKey sets */ + export function UnionMany(T: [...T]): UnionMany { + return ( + T.length === 1 + ? T[0] + : TakeLeft(T, + (L, R) => Union(L, UnionMany(R)), + () => [] + ) + ) as UnionMany } +} +// ---------------------------------------------------------------- +// Resolver: KeyResolver +// ---------------------------------------------------------------- +// prettier-ignore +export namespace KeyResolver { // ---------------------------------------------------------------- - // UnionDistinct + // Collect // ---------------------------------------------------------------- - export type UnionDistinct = ( - T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] - ? Includes extends true - ? [L, ...UnionDistinct] - : [...UnionDistinct] + export type Collect = ( + T extends [infer L extends TSchema, ...infer R extends TSchema[]] + ? [Resolve, ...Collect] : [] ) - export function UnionDistinct(T: [...T], S: [...S]): UnionDistinct { + export function Collect(T: [...T]): Collect { const [L, ...R] = T return ( T.length > 0 - ? Includes(S, L) === true - ? [L, ...UnionDistinct(R, S)] - : [...UnionDistinct(R, S)] + ? [Resolve(L), ...Collect(R)] : [] - ) as UnionDistinct + ) as Collect } // ---------------------------------------------------------------- - // UnionIntersection + // Intersect // ---------------------------------------------------------------- - export type UnionIntersection = ( - T extends [infer L extends PropertyKey[]] - ? L - : T extends [infer L extends PropertyKey[], ...infer R extends PropertyKey[][]] - ? UnionDistinct> - : [] - ) - export function UnionIntersection(T: [...T]): UnionIntersection { + export type Intersect> = ( + PropertyKeys.UnionMany + ) + export function Intersect(T: [...T], C = Collect(T)): Intersect { return ( - T.length === 1 - ? T[0] - : Into(() => { - const [L, ...R] = T - return L.length > 0 - ? UnionDistinct(L, UnionIntersection(R)) - : [] - }) - ) as UnionIntersection + PropertyKeys.UnionMany(C as PropertyKey[][]) as Intersect + ) } // ---------------------------------------------------------------- // Union // ---------------------------------------------------------------- export type Union> = ( - UnionIntersection + PropertyKeys.IntersectMany ) export function Union(T: [...T], C = Collect(T)): Union { return ( - UnionIntersection(C as PropertyKey[][]) as Union + PropertyKeys.IntersectMany(C as PropertyKey[][]) as Union ) } // ---------------------------------------------------------------- @@ -2736,7 +2760,7 @@ export namespace KeyResolver { // ---------------------------------------------------------------- export type TupleNext = ( I extends [infer L extends string, ...infer _] - ? Increment.Next + ? Counter.Next : '0' ) export type TupleCollect = ( @@ -2823,7 +2847,7 @@ export namespace KeyResolver { } } // ------------------------------------------------------------------ -// IndexedResolver +// Resolver: IndexResolver // ------------------------------------------------------------------ // prettier-ignore export namespace IndexResolver { @@ -2899,10 +2923,10 @@ export namespace IndexResolver { } } // ------------------------------------------------------------------ -// AccessResolver +// Resolver: IndexAccessResolver // ------------------------------------------------------------------ // prettier-ignore -export namespace AccessResolver { +export namespace IndexAccessResolver { // ---------------------------------------------------------------- // Collect // ---------------------------------------------------------------- @@ -3071,7 +3095,7 @@ export namespace AccessResolver { } } // ------------------------------------------------------------------ -// KeyOfResolver +// Resolver: KeyOfResolver // ------------------------------------------------------------------ // prettier-ignore export namespace KeyOfResolver { @@ -3107,9 +3131,10 @@ export namespace KeyOfResolver { ) as unknown as Resolve } } -// -------------------------------------------------------------------------- + +// ------------------------------------------------------------------ // KeyArrayResolver -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export class KeyArrayResolverError extends TypeBoxError {} // prettier-ignore export namespace KeyArrayResolver { @@ -3127,9 +3152,9 @@ export namespace KeyArrayResolver { ) } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // UnionResolver -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export namespace UnionResolver { function* TUnion(union: TUnion): IterableIterator { for (const schema of union.anyOf) { @@ -3145,9 +3170,9 @@ export namespace UnionResolver { return Type.Union([...TUnion(union)], { ...union }) } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TemplateLiteralPattern -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export class TemplateLiteralPatternError extends TypeBoxError {} // prettier-ignore export namespace TemplateLiteralPattern { @@ -3174,9 +3199,9 @@ export namespace TemplateLiteralPattern { return `^${kinds.map((schema) => Visit(schema, '')).join('')}\$` } } -// -------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------ // TemplateLiteralResolver -// -------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------ export namespace TemplateLiteralResolver { /** Resolves a template literal as a TUnion */ export function Resolve(template: TTemplateLiteral): TNever | TString | TUnion { @@ -3186,9 +3211,9 @@ export namespace TemplateLiteralResolver { return Type.Union(literals) } } -// -------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------ // TemplateLiteralParser -// -------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------ export class TemplateLiteralParserError extends TypeBoxError {} // prettier-ignore export namespace TemplateLiteralParser { @@ -3305,9 +3330,9 @@ export namespace TemplateLiteralParser { return Parse(pattern.slice(1, pattern.length - 1)) } } -// -------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------ // TemplateLiteralFinite -// -------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------ export class TemplateLiteralFiniteError extends TypeBoxError {} // prettier-ignore export namespace TemplateLiteralFinite { @@ -3348,9 +3373,9 @@ export namespace TemplateLiteralFinite { ) } } -// -------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------ // TemplateLiteralGenerator -// -------------------------------------------------------------------------------------- +// ------------------------------------------------------------------------------ export class TemplateLiteralGeneratorError extends TypeBoxError {} // prettier-ignore export namespace TemplateLiteralGenerator { @@ -3458,13 +3483,13 @@ export class TransformEncodeBuilder> } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TypeOrdinal: Used for auto $id generation -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ let TypeOrdinal = 0 -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // TypeBuilder -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ export class TypeBuilderError extends TypeBoxError {} export class TypeBuilder { /** `[Internal]` Creates a schema without `static` and `params` types */ @@ -3487,9 +3512,9 @@ export class TypeBuilder { return JSON.parse(JSON.stringify(schema)) } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // JsonTypeBuilder -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // prettier-ignore export class JsonTypeBuilder extends TypeBuilder { // ------------------------------------------------------------------------ @@ -3579,13 +3604,13 @@ export class JsonTypeBuilder extends TypeBuilder { ) as TExtract } /** `[Json]` Returns an Indexed property type for the given keys */ - public Index>(T: T, keys: K, options?: SchemaOptions): AccessResolver.Resolve + public Index>(T: T, keys: K, options?: SchemaOptions): IndexAccessResolver.Resolve /** `[Json]` Returns an Indexed property type for the given keys */ - public Index(T: T, K: [...K], options?: SchemaOptions): AccessResolver.Resolve + public Index(T: T, K: [...K], options?: SchemaOptions): IndexAccessResolver.Resolve /** `[Json]` Returns an Indexed property type for the given keys */ public Index(T: TSchema, K: unknown, options: SchemaOptions = {}): any { const keys = TypeGuard.TSchema(K) ? IndexResolver.Resolve(K) : K as string[] - const type = AccessResolver.Resolve(T, keys) + const type = IndexAccessResolver.Resolve(T, keys) return TypeClone.Type(type, options) } /** `[Json]` Creates an Integer type */ @@ -3837,9 +3862,9 @@ export class JsonTypeBuilder extends TypeBuilder { return { ...Intrinsic.Map(TypeClone.Type(schema), 'Uppercase'), ...options } } } -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // JavaScriptTypeBuilder -// -------------------------------------------------------------------------- +// ------------------------------------------------------------------ // prettier-ignore export class JavaScriptTypeBuilder extends JsonTypeBuilder { /** `[JavaScript]` Creates a AsyncIterator type */ diff --git a/src/value/transform.ts b/src/value/transform.ts index 157cea4e2..33545e963 100644 --- a/src/value/transform.ts +++ b/src/value/transform.ts @@ -174,10 +174,10 @@ export namespace DecodeTransform { // prettier-ignore function TIntersect(schema: Types.TIntersect, references: Types.TSchema[], value: any) { if (!IsPlainObject(value) || IsValueType(value)) return Default(schema, value) - const knownKeys = Types.KeyResolver.Resolve(schema, { includePatterns: false }) + const knownKeys = Types.KeyResolver.Resolve(schema) as string[] const knownProperties = knownKeys.reduce((value, key) => { return (key in value) - ? { ...value, [key]: Visit(Types.AccessResolver.Resolve(schema, [key]), references, value[key]) } + ? { ...value, [key]: Visit(Types.IndexAccessResolver.Resolve(schema, [key]), references, value[key]) } : value }, value) if (!Types.TypeGuard.TTransform(schema.unevaluatedProperties)) { @@ -198,7 +198,7 @@ export namespace DecodeTransform { // prettier-ignore function TObject(schema: Types.TObject, references: Types.TSchema[], value: any) { if (!IsPlainObject(value)) return Default(schema, value) - const knownKeys = Types.KeyResolver.Resolve(schema, { includePatterns: false }) + const knownKeys = Types.KeyResolver.Resolve(schema) const knownProperties = knownKeys.reduce((value, key) => { return (key in value) ? { ...value, [key]: Visit(schema.properties[key], references, value[key]) } @@ -315,10 +315,10 @@ export namespace EncodeTransform { function TIntersect(schema: Types.TIntersect, references: Types.TSchema[], value: any) { const defaulted = Default(schema, value) if (!IsPlainObject(value) || IsValueType(value)) return defaulted - const knownKeys = Types.KeyResolver.Resolve(schema, { includePatterns: false }) + const knownKeys = Types.KeyResolver.Resolve(schema) as string[] const knownProperties = knownKeys.reduce((value, key) => { return key in defaulted - ? { ...value, [key]: Visit(Types.AccessResolver.Resolve(schema, [key]), references, value[key]) } + ? { ...value, [key]: Visit(Types.IndexAccessResolver.Resolve(schema, [key]), references, value[key]) } : value }, defaulted) if (!Types.TypeGuard.TTransform(schema.unevaluatedProperties)) { @@ -339,7 +339,7 @@ export namespace EncodeTransform { function TObject(schema: Types.TObject, references: Types.TSchema[], value: any) { const defaulted = Default(schema, value) if (!IsPlainObject(value)) return defaulted - const knownKeys = Types.KeyResolver.Resolve(schema, { includePatterns: false }) + const knownKeys = Types.KeyResolver.Resolve(schema) as string[] const knownProperties = knownKeys.reduce((value, key) => { return key in value ? { ...value, [key]: Visit(schema.properties[key], references, value[key]) }