diff --git a/examples/index.ts b/examples/index.ts index dbf625510..cd51a6972 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -1,92 +1,16 @@ import { TypeSystem } from '@sinclair/typebox/system' import { TypeCompiler } from '@sinclair/typebox/compiler' import { Value, ValuePointer } from '@sinclair/typebox/value' -import { Type, Static, TSchema, TProperties, TArray, TLiteral, TTemplateLiteral, TypeGuard, TemplateLiteralParser, TOptional, UnionTypeIsOptional, TRecursive, TIntersect, TUnion, TTuple, TNever, TString, TNumber, UnionType, IntersectType } from '@sinclair/typebox' +import { Type, Indexer, Accessor } from '@sinclair/typebox' import { TObject } from '@sinclair/typebox' +const A = Indexer.Keys(Type.Number(), { includePatterns: true }) +const B = Accessor.Resolve( + Type.Object({ + x: Type.Number(), + }), + A, +) - -// ------------------------------------------------------------------ -// TIndex -// ------------------------------------------------------------------ -// prettier-ignore -export type TIndexDiscardNever = - T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? L extends TNever - ? [...TIndexDiscardNever] - : [L, ...TIndexDiscardNever] - : [] -export type TIndexProperty = K extends keyof T ? T[K] : TNever -export type TIndexTuple = K extends keyof T ? T[K] : TNever -export type TIndexArray = K extends number ? T : TNever -// ------------------------------------------------------------------ -// TIndex: Intersect -// ------------------------------------------------------------------ -export type TIndexIntersect = - T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? TIndexKey extends infer N extends TSchema - ? N extends TNever - ? [...TIndexIntersect] - : [N, ...TIndexIntersect] - : [] - : [] -// ------------------------------------------------------------------ -// TIndex: Union -// ------------------------------------------------------------------ -// prettier-ignore -export type TIndexUnionCollect = - T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? [TIndexKey, ...TIndexUnionCollect] - : [] -// prettier-ignore -export type TIndexUnionCheck = - T extends [infer L extends TSchema[], ...infer R extends TSchema[][]] - ? L extends [] - ? false - : TIndexUnionCheck - : true -// prettier-ignore -export type TIndexUnion< - T extends TSchema[], K extends PropertyKey, - G extends TSchema[] = TIndexUnionCollect, - C extends TSchema[] = TIndexDiscardNever -> = C -// prettier-ignore -export type TIndexKey = - T extends TRecursive ? TIndexKey : - T extends TIntersect ? IntersectType> : - T extends TUnion ? UnionType> : - T extends TTuple ? TIndexTuple : - T extends TArray ? TIndexArray : - T extends TObject ? TIndexProperty : - TNever -// prettier-ignore -export type TIndexKeys = - K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] - ? [TIndexKey, ...TIndexKeys] - : [] - -export type TIndex = UnionType> - -type A = TUnion<[TObject<{ - x: TString; - y: TLiteral<1>; -}>, TObject<{ - x: TNumber; - y: TNumber; -}>]> - -type B = TIntersect<[TObject<{ - x: TString; - y: TNumber; -}>, TObject<{ - x: TString; -}>]> - -type I = TIntersect<[A, B]> - -// TIntersect<[TUnion<[TLiteral<1>, TNumber]>, TNumber]> -type C = TIndex - -type S = Static \ No newline at end of file +console.log(A, B) diff --git a/src/compiler/compiler.ts b/src/compiler/compiler.ts index fe03f6d2e..f0f109deb 100644 --- a/src/compiler/compiler.ts +++ b/src/compiler/compiler.ts @@ -253,11 +253,11 @@ export namespace TypeCompiler { function* TIntersect(schema: Types.TIntersect, references: Types.TSchema[], value: string): IterableIterator { const check1 = schema.allOf.map((schema: Types.TSchema) => CreateExpression(schema, references, value)).join(' && ') if (schema.unevaluatedProperties === false) { - const keyCheck = CreateVariable(`${new RegExp(Types.KeyResolver.ResolvePattern(schema))};`) + const keyCheck = CreateVariable(`${new RegExp(Types.Indexer.Pattern(schema))};`) const check2 = `Object.getOwnPropertyNames(${value}).every(key => ${keyCheck}.test(key))` yield `(${check1} && ${check2})` } else if (Types.TypeGuard.TSchema(schema.unevaluatedProperties)) { - const keyCheck = CreateVariable(`${new RegExp(Types.KeyResolver.ResolvePattern(schema))};`) + const keyCheck = CreateVariable(`${new RegExp(Types.Indexer.Pattern(schema))};`) const check2 = `Object.getOwnPropertyNames(${value}).every(key => ${keyCheck}.test(key) || ${CreateExpression(schema.unevaluatedProperties, references, `${value}[key]`)})` yield `(${check1} && ${check2})` } else { diff --git a/src/errors/errors.ts b/src/errors/errors.ts index 9f09e1f55..5e413d582 100644 --- a/src/errors/errors.ts +++ b/src/errors/errors.ts @@ -262,7 +262,7 @@ function* TIntersect(schema: Types.TIntersect, references: Types.TSchema[], path } } if (schema.unevaluatedProperties === false) { - const keyCheck = new RegExp(Types.KeyResolver.ResolvePattern(schema)) + const keyCheck = new RegExp(Types.Indexer.Pattern(schema)) for (const valueKey of Object.getOwnPropertyNames(value)) { if (!keyCheck.test(valueKey)) { yield Create(ValueErrorType.IntersectUnevaluatedProperties, schema, `${path}/${valueKey}`, value) @@ -270,7 +270,7 @@ function* TIntersect(schema: Types.TIntersect, references: Types.TSchema[], path } } if (typeof schema.unevaluatedProperties === 'object') { - const keyCheck = new RegExp(Types.KeyResolver.ResolvePattern(schema)) + const keyCheck = new RegExp(Types.Indexer.Pattern(schema)) for (const valueKey of Object.getOwnPropertyNames(value)) { if (!keyCheck.test(valueKey)) { const next = Visit(schema.unevaluatedProperties, references, `${path}/${valueKey}`, value[valueKey]).next() diff --git a/src/typebox.ts b/src/typebox.ts index 77c186f80..3dbbbe683 100644 --- a/src/typebox.ts +++ b/src/typebox.ts @@ -73,87 +73,87 @@ export type TOptional = T & { [Optional]: 'Optional' } // -------------------------------------------------------------------------- // prettier-ignore export type ReadonlyUnwrapType = - T extends TReadonly ? ReadonlyUnwrapType : + T extends TReadonly ? ReadonlyUnwrapType : T extends TOptional ? TOptional> : T // prettier-ignore -export type ReadonlyUnwrapRest = +export type ReadonlyUnwrapRest = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? L extends TReadonly - ? [ReadonlyUnwrapType, ...ReadonlyUnwrapRest] - : [L, ...ReadonlyUnwrapRest] - : [] + ? L extends TReadonly + ? [ReadonlyUnwrapType, ...ReadonlyUnwrapRest] + : [L, ...ReadonlyUnwrapRest] + : [] // -------------------------------------------------------------------------- // Optional Unwrap // -------------------------------------------------------------------------- // prettier-ignore export type OptionalUnwrapType = T extends TReadonly ? TReadonly> : - T extends TOptional ? OptionalUnwrapType : + T extends TOptional ? OptionalUnwrapType : T // prettier-ignore -export type OptionalUnwrapRest = +export type OptionalUnwrapRest = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? L extends TOptional - ? [OptionalUnwrapType, ...OptionalUnwrapRest] - : [L, ...OptionalUnwrapRest] - : [] + ? L extends TOptional + ? [OptionalUnwrapType, ...OptionalUnwrapRest] + : [L, ...OptionalUnwrapRest] + : [] // ------------------------------------------------------------------ // DistinctRest // ------------------------------------------------------------------ // prettier-ignore -export type DistinctRestIncludes = - T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? C extends L - ? true - : DistinctRestIncludes - : false +export type DistinctRestIncludes = + T extends [infer L extends TSchema, ...infer R extends TSchema[]] + ? C extends L + ? true + : DistinctRestIncludes + : false // prettier-ignore -export type DistinctRest = +export type DistinctRest = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? DistinctRestIncludes extends false - ? DistinctRest - : DistinctRest - : Acc + ? DistinctRestIncludes extends false + ? DistinctRest + : DistinctRest + : Acc // -------------------------------------------------------------------------- // IntersectType // -------------------------------------------------------------------------- // prettier-ignore -export type IntersectTypeIsOptional = - T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? L extends TOptional - ? IntersectTypeIsOptional - : false +export type IntersectTypeIsOptional = + T extends [infer L extends TSchema, ...infer R extends TSchema[]] + ? L extends TOptional + ? IntersectTypeIsOptional + : false : true // prettier-ignore -export type IntersectTypeOptional> = +export type IntersectTypeOptional> = IntersectTypeIsOptional extends true - ? TOptional> - : TIntersect + ? TOptional> + : TIntersect // prettier-ignore export type IntersectType = //extends TSchema[] = DistinctRest> = - D extends [] ? TNever : - D extends [TSchema] ? T[0] : + D extends [] ? TNever : + D extends [TSchema] ? T[0] : IntersectTypeOptional // -------------------------------------------------------------------------- // UnionType // -------------------------------------------------------------------------- // prettier-ignore -export type UnionTypeIsOptional = +export type UnionTypeIsOptional = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? L extends TOptional - ? true - : UnionTypeIsOptional - : false + ? L extends TOptional + ? true + : UnionTypeIsOptional + : false // prettier-ignore -export type UnionTypeOptional> = +export type UnionTypeOptional> = UnionTypeIsOptional extends true - ? TOptional> - : TUnion + ? TOptional> + : TUnion // prettier-ignore export type UnionType = // = DistinctRest> = - D extends [] ? TNever : - D extends [TSchema] ? T[0] : + D extends [] ? TNever : + D extends [TSchema] ? T[0] : UnionTypeOptional // -------------------------------------------------------------------------- // TSchema @@ -274,15 +274,15 @@ export interface TAsyncIterator extends TSchema { // TAwaited // ------------------------------------------------------------------------------- // prettier-ignore -export type TAwaitedRest = +export type TAwaitedRest = T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? [TAwaited, ...TAwaitedRest] : [] // prettier-ignore -export type TAwaited = +export type TAwaited = T extends TIntersect ? TIntersect> : - T extends TUnion ? TUnion> : - T extends TPromise ? TAwaited : + T extends TUnion ? TUnion> : + T extends TPromise ? TAwaited : T // -------------------------------------------------------------------------- // TBigInt @@ -312,21 +312,21 @@ export type TInstanceType> = T['retur // TComposite // -------------------------------------------------------------------------- // prettier-ignore -export type TCompositeKeys = - T extends [infer L extends TObject, ...infer R extends TObject[]] - ? keyof L['properties'] | TCompositeKeys - : never +export type TCompositeKeys = + T extends [infer L extends TObject, ...infer R extends TObject[]] + ? keyof L['properties'] | TCompositeKeys + : never // prettier-ignore -export type TCompositeIndex, K extends string[]> = - K extends [infer L extends string, ...infer R extends string[]] - ? { [_ in L]: TIndex } & TCompositeIndex +export type TCompositeIndex, K extends string[]> = + K extends [infer L extends string, ...infer R extends string[]] + ? { [_ in L]: TIndex } & TCompositeIndex : {} // prettier-ignore -export type TCompositeReduce = UnionToTuple> extends infer K - ? Evaluate, Assert>> +export type TCompositeReduce = UnionToTuple> extends infer K + ? Evaluate, Assert>> : {} // ^ indexed via intersection of T // prettier-ignore -export type TComposite = TIntersect extends TIntersect +export type TComposite = TIntersect extends TIntersect ? TObject> : TObject<{}> // -------------------------------------------------------------------------- @@ -378,11 +378,11 @@ export interface TEnum = Record = - (Static extends Static ? T : U) extends infer O extends TSchema ? - UnionToTuple extends [infer X extends TSchema, infer Y extends TSchema] - ? TUnion<[X, Y]> - : O +export type TExtends = + (Static extends Static ? T : U) extends infer O extends TSchema ? + UnionToTuple extends [infer X extends TSchema, infer Y extends TSchema] + ? TUnion<[X, Y]> + : O : never // -------------------------------------------------------------------------- // TExclude @@ -394,9 +394,9 @@ export type TExcludeArray = AssertRest> extends Static ? never : T[K] }[number]>> extends infer R extends TSchema[] ? UnionType : never // prettier-ignore -export type TExclude = - T extends TTemplateLiteral ? TExcludeTemplateLiteral : - T extends TUnion ? TExcludeArray : +export type TExclude = + T extends TTemplateLiteral ? TExcludeTemplateLiteral : + T extends TUnion ? TExcludeArray : T extends U ? TNever : T // -------------------------------------------------------------------------- // TExtract @@ -405,12 +405,12 @@ export type TExtractTemplateLiteralResult = UnionType = Extract, Static> extends infer S ? TExtractTemplateLiteralResult> : never // prettier-ignore export type TExtractArray = AssertRest> extends Static ? T[K] : never -}[number]>> extends infer R extends TSchema[] ? UnionType : never + { [K in keyof T]: Static> extends Static ? T[K] : never + }[number]>> extends infer R extends TSchema[] ? UnionType : never // prettier-ignore -export type TExtract = - T extends TTemplateLiteral ? TExtractTemplateLiteral : - T extends TUnion ? TExtractArray : +export type TExtract = + T extends TTemplateLiteral ? TExtractTemplateLiteral : + T extends TUnion ? TExtractArray : T extends U ? T : T // -------------------------------------------------------------------------- // TFunction @@ -426,109 +426,78 @@ export interface TFunction> = F extends true ? UnionToTuple> : [] -export type TKeyResolverUnion = T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? [...TKeyResolver, ...TKeyResolverUnion] : [] -export type TKeyResolverLiteral = T extends PropertyKey ? [T] : [] +export type TIndexerTemplateLiteral> = 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] : [] // prettier-ignore -export type TKeyResolver = - T extends TTemplateLiteral ? TKeyResolverTemplateLiteral : - T extends TUnion ? TKeyResolverUnion : - T extends TLiteral ? TKeyResolverLiteral : - T extends TString ? [] : - T extends TNumber ? [] : - T extends TInteger ? [] : +export type TIndexer = + T extends TTemplateLiteral ? TIndexerTemplateLiteral : + T extends TUnion ? TIndexerUnion : + T extends TLiteral ? TIndexerLiteral : + T extends TNumber ? ['number'] : // tuple + array indexing + T extends TInteger ? ['number'] : // tuple + array indexing T extends TBigInt ? [] : + T extends TString ? [] : [] // ------------------------------------------------------------------ // TIndex // ------------------------------------------------------------------ -export type TIndexProperties = K extends keyof T ? [T[K]] : [] -export type TIndexTuple = K extends keyof T ? [T[K]] : [] -export type TIndexArray = K extends number ? [T] : [] +export type TIndexProperty = K extends keyof T ? T[K] : TNever +export type TIndexTuple = K extends keyof T ? T[K] : K extends 'number' ? UnionType : TNever +export type TIndexArray = K extends number ? T : TNever // prettier-ignore -export type TIndexIntersect = - T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? L extends TIntersect - ? [IntersectType>, ...TIndexIntersect] - : L extends TUnion - ? [UnionType>, ...TIndexIntersect] - : [...TIndexKeyResolve, ...TIndexIntersect] - : [] -// prettier-ignore -export type TIndexUnionGather = +export type TIndexRest = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? [TIndexKeyResolve, ...TIndexUnionGather] - : [] -// prettier-ignore -export type TIndexUnionCheck = - T extends [infer L extends TSchema[], ...infer R extends TSchema[][]] - ? L extends [] - ? false - : TIndexUnionCheck - : true -// prettier-ignore -export type TIndexUnionFinal = - T extends [infer L extends TSchema[], ...infer R extends TSchema[][]] - ? [...L, ...TIndexUnionFinal] - : [] -// prettier-ignore -export type TIndexUnion, C extends boolean = TIndexUnionCheck> = - C extends true - ? TIndexUnionFinal - : [] -// prettier-ignore -export type TIndexKeyResolve = - T extends TRecursive ? TIndexKeyResolve : - T extends TIntersect ? TIndexIntersect : - T extends TUnion ? TIndexUnion : + ? TIndexKey extends infer N extends TSchema + ? N extends TNever + ? [...TIndexRest] + : [N, ...TIndexRest] + : [] + : [] +// prettier-ignore +export type TIndexKey = + T extends TRecursive ? TIndexKey : + T extends TIntersect ? IntersectType> : + T extends TUnion ? UnionType> : T extends TTuple ? TIndexTuple : T extends TArray ? TIndexArray : - T extends TObject ? TIndexProperties : - [] -// prettier-ignore -export type TIndexKey> = - R extends TSchema[] - ? UnionType - : TNever + T extends TObject ? TIndexProperty : + TNever // prettier-ignore -export type TIndexKeysResolve = +export type TIndexKeys = K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] - ? [TIndexKey, ...TIndexKeysResolve] - : [] -// prettier-ignore -export type TIndexKeys> = - R extends TSchema[] - ? IntersectType - : TNever -export type TIndex = TIndexKeys + ? [TIndexKey, ...TIndexKeys] + : [] + +export type TIndex = UnionType> // -------------------------------------------------------------------------- // TIntrinsic // -------------------------------------------------------------------------- export type TIntrinsicMode = 'Uppercase' | 'Lowercase' | 'Capitalize' | 'Uncapitalize' // prettier-ignore export type TIntrinsicTemplateLiteral = - M extends ('Lowercase' | 'Uppercase') ? - T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]] - ? [TIntrinsic, ...TIntrinsicTemplateLiteral] - : T : - M extends ('Capitalize' | 'Uncapitalize') - ? T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]] - ? [TIntrinsic, ...TIntrinsicTemplateLiteral] - : T - : T -// prettier-ignore -export type TIntrinsicLiteral = - T extends string ? - M extends 'Uncapitalize' ? Uncapitalize : - M extends 'Capitalize' ? Capitalize : - M extends 'Uppercase' ? Uppercase : - M extends 'Lowercase' ? Lowercase : - string + M extends ('Lowercase' | 'Uppercase') ? + T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]] + ? [TIntrinsic, ...TIntrinsicTemplateLiteral] + : T : + M extends ('Capitalize' | 'Uncapitalize') + ? T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]] + ? [TIntrinsic, ...TIntrinsicTemplateLiteral] + : T + : T +// prettier-ignore +export type TIntrinsicLiteral = + T extends string ? + M extends 'Uncapitalize' ? Uncapitalize : + M extends 'Capitalize' ? Capitalize : + M extends 'Uppercase' ? Uppercase : + M extends 'Lowercase' ? Lowercase : + string : T // prettier-ignore -export type TIntrinsicRest = +export type TIntrinsicRest = T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? [TIntrinsic, ...TIntrinsicRest] : [] @@ -573,23 +542,23 @@ export interface TIterator extends TSchema { // -------------------------------------------------------------------------- // prettier-ignore export type TKeyOfProperties = Discard extends infer S - ? UnionToTuple<{[K in keyof S]: TLiteral>}[keyof S]> + ? UnionToTuple<{ [K in keyof S]: TLiteral> }[keyof S]> : [], undefined> // note: optional properties produce undefined types in tuple result. discard. // prettier-ignore export type TKeyOfIndicesArray = UnionToTuple // prettier-ignore export type TKeyOfIndices = AssertRest extends infer R ? { - [K in keyof R] : TLiteral> -}: []> + [K in keyof R]: TLiteral> +} : []> // prettier-ignore export type TKeyOf = ( T extends TRecursive ? TKeyOfProperties : - T extends TIntersect ? TKeyOfProperties : - T extends TUnion ? TKeyOfProperties : - T extends TObject ? TKeyOfProperties : - T extends TTuple ? TKeyOfIndices : - T extends TArray ? [TNumber] : - T extends TRecord ? [K] : + T extends TIntersect ? TKeyOfProperties : + T extends TUnion ? TKeyOfProperties : + T extends TObject ? TKeyOfProperties : + T extends TTuple ? TKeyOfIndices : + T extends TArray ? [TNumber] : + T extends TRecord ? [K] : [] ) extends infer R ? UnionType> : never // -------------------------------------------------------------------------- @@ -681,11 +650,11 @@ export interface TObject extends TSchema, O export type TOmitProperties = Evaluate>> export type TOmitRest = AssertRest<{ [K2 in keyof T]: TOmit, K> }> // prettier-ignore -export type TOmit = +export type TOmit = T extends TRecursive ? TRecursive> : - T extends TIntersect ? TIntersect> : - T extends TUnion ? TUnion> : - T extends TObject ? TObject> : + T extends TIntersect ? TIntersect> : + T extends TUnion ? TUnion> : + T extends TObject ? TObject> : T // -------------------------------------------------------------------------- // TParameters @@ -698,18 +667,18 @@ export type TPartialObjectArray = AssertRest<{ [K in keyof export type TPartialRest = AssertRest<{ [K in keyof T]: TPartial> }> // prettier-ignore export type TPartialProperties = Evaluate) ? TReadonlyOptional : - T[K] extends (TReadonly) ? TReadonlyOptional : - T[K] extends (TOptional) ? TOptional : - TOptional + [K in keyof T]: + T[K] extends (TReadonlyOptional) ? TReadonlyOptional : + T[K] extends (TReadonly) ? TReadonlyOptional : + T[K] extends (TOptional) ? TOptional : + TOptional }>> // prettier-ignore -export type TPartial = - T extends TRecursive ? TRecursive> : - T extends TIntersect ? TIntersect> : - T extends TUnion ? TUnion> : - T extends TObject ? TObject> : +export type TPartial = + T extends TRecursive ? TRecursive> : + T extends TIntersect ? TIntersect> : + T extends TUnion ? TUnion> : + T extends TObject ? TObject> : T // -------------------------------------------------------------------------- // TPick @@ -717,16 +686,16 @@ export type TPartial = // 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 -export type TPickProperties = +export type TPickProperties = Pick, keyof T>> extends infer R ? ({ [K in keyof R]: AssertType extends TSchema ? R[K] : never - }): never + }) : never export type TPickRest = { [K2 in keyof T]: TPick, K> } // prettier-ignore -export type TPick = +export type TPick = T extends TRecursive ? TRecursive> : - T extends TIntersect ? TIntersect> : - T extends TUnion ? TUnion> : + T extends TIntersect ? TIntersect> : + T extends TUnion ? TUnion> : T extends TObject ? TObject> : T // -------------------------------------------------------------------------- @@ -750,13 +719,13 @@ export type TRecordFromUnionRest = K ext L extends TUnion ? TRecordFromUnionRest & TRecordFromUnionRest, T> : L extends TLiteralString ? TRecordFromUnionLiteralString & TRecordFromUnionRest, T> : L extends TLiteralNumber ? TRecordFromUnionLiteralNumber & TRecordFromUnionRest, T> : -{}) : {} + {}) : {} export type TRecordFromUnion = Ensure>>>> export type TRecordFromTemplateLiteralKeyInfinite = Ensure> export type TRecordFromTemplateLiteralKeyFinite> = Ensure]: T }>>> // prettier-ignore -export type TRecordFromTemplateLiteralKey = IsTemplateLiteralFinite extends false - ? TRecordFromTemplateLiteralKeyInfinite +export type TRecordFromTemplateLiteralKey = IsTemplateLiteralFinite extends false + ? TRecordFromTemplateLiteralKeyInfinite : TRecordFromTemplateLiteralKeyFinite export type TRecordFromLiteralStringKey = Ensure> export type TRecordFromLiteralNumberKey = Ensure> @@ -764,7 +733,7 @@ export type TRecordFromStringKey = Ensure< export type TRecordFromNumberKey = Ensure> export type TRecordFromIntegerKey = Ensure> // prettier-ignore -export type TRecordResolve = +export type TRecordResolve = K extends TEnum ? TRecordFromEnumKey : // Enum before Union (intercept Hint) K extends TUnion ? TRecordFromUnion : K extends TTemplateLiteral ? TRecordFromTemplateLiteralKey : @@ -816,18 +785,18 @@ export type TReturnType = T['returns'] export type TRequiredRest = AssertRest<{ [K in keyof T]: TRequired> }> // prettier-ignore export type TRequiredProperties = Evaluate) ? TReadonly : - T[K] extends (TReadonly) ? TReadonly : - T[K] extends (TOptional) ? S : - T[K] + [K in keyof T]: + T[K] extends (TReadonlyOptional) ? TReadonly : + T[K] extends (TReadonly) ? TReadonly : + T[K] extends (TOptional) ? S : + T[K] }>> // prettier-ignore -export type TRequired = - T extends TRecursive ? TRecursive> : - T extends TIntersect ? TIntersect> : - T extends TUnion ? TUnion> : - T extends TObject ? TObject> : +export type TRequired = + T extends TRecursive ? TRecursive> : + T extends TIntersect ? TIntersect> : + T extends TUnion ? TUnion> : + T extends TObject ? TObject> : T // -------------------------------------------------------------------------- // TString @@ -853,12 +822,12 @@ export type StringFormatOption = | 'regex' | ({} & string) // prettier-ignore -export type StringContentEncodingOption = - | '7bit' - | '8bit' - | 'binary' - | 'quoted-printable' - | 'base64' +export type StringContentEncodingOption = + | '7bit' + | '8bit' + | 'binary' + | 'quoted-printable' + | 'base64' | ({} & string) export interface StringOptions extends SchemaOptions { /** The maximum string length */ @@ -892,23 +861,23 @@ export interface TSymbol extends TSchema, SchemaOptions { // TTemplateLiteralParserDsl // ------------------------------------------------------------------------- // prettier-ignore -export type TTemplateLiteralDslParserUnionLiteral = - T extends `${infer L}|${infer R}` ? [TLiteral>, ...TTemplateLiteralDslParserUnionLiteral] : - T extends `${infer L}` ? [TLiteral>] : +export type TTemplateLiteralDslParserUnionLiteral = + T extends `${infer L}|${infer R}` ? [TLiteral>, ...TTemplateLiteralDslParserUnionLiteral] : + T extends `${infer L}` ? [TLiteral>] : [] export type TTemplateLiteralDslParserUnion = UnionType> // prettier-ignore -export type TTemplateLiteralDslParserTerminal = - T extends 'boolean' ? TBoolean : - T extends 'bigint' ? TBigInt : +export type TTemplateLiteralDslParserTerminal = + T extends 'boolean' ? TBoolean : + T extends 'bigint' ? TBigInt : T extends 'number' ? TNumber : T extends 'string' ? TString : TTemplateLiteralDslParserUnion // prettier-ignore -export type TTemplateLiteralDslParserTemplate = +export type TTemplateLiteralDslParserTemplate = T extends `{${infer L}}${infer R}` ? [TTemplateLiteralDslParserTerminal, ...TTemplateLiteralDslParserTemplate] : - T extends `${infer L}$${infer R}` ? [TLiteral, ...TTemplateLiteralDslParserTemplate] : - T extends `${infer L}` ? [TLiteral] : + T extends `${infer L}$${infer R}` ? [TLiteral, ...TTemplateLiteralDslParserTemplate] : + T extends `${infer L}` ? [TLiteral] : [] export type TTemplateLiteralDslParser = Ensure, TTemplateLiteralKind[]>>> // -------------------------------------------------------------------------- @@ -916,33 +885,33 @@ export type TTemplateLiteralDslParser = Ensure = - T extends TTemplateLiteral ? IsTemplateLiteralFiniteArray> : - T extends TUnion ? IsTemplateLiteralFiniteArray> : + T extends TTemplateLiteral ? IsTemplateLiteralFiniteArray> : + T extends TUnion ? IsTemplateLiteralFiniteArray> : T extends TString ? false : T extends TBoolean ? false : T extends TNumber ? false : T extends TInteger ? false : T extends TBigInt ? false : - T extends TLiteral ? true : + T extends TLiteral ? true : false // prettier-ignore -export type IsTemplateLiteralFiniteArray = +export type IsTemplateLiteralFiniteArray = T extends [infer L, ...infer R] ? IsTemplateLiteralFiniteCheck extends false ? false : IsTemplateLiteralFiniteArray> : true export type IsTemplateLiteralFinite = T extends TTemplateLiteral ? IsTemplateLiteralFiniteArray : false export type TTemplateLiteralKind = TUnion | TLiteral | TInteger | TTemplateLiteral | TNumber | TBigInt | TString | TBoolean | TNever // prettier-ignore -export type TTemplateLiteralConst = +export type TTemplateLiteralConst = T extends TUnion ? { [K in keyof U]: TTemplateLiteralUnion, Acc> }[number] : - T extends TTemplateLiteral ? `${Static}` : + T extends TTemplateLiteral ? `${Static}` : T extends TLiteral ? `${U}` : - T extends TString ? `${string}` : - T extends TNumber ? `${number}` : - T extends TBigInt ? `${bigint}` : + T extends TString ? `${string}` : + T extends TNumber ? `${number}` : + T extends TBigInt ? `${bigint}` : T extends TBoolean ? `${boolean}` : never // prettier-ignore -export type TTemplateLiteralUnion = +export type TTemplateLiteralUnion = T extends [infer L, ...infer R] ? `${TTemplateLiteralConst}${TTemplateLiteralUnion, Acc>}` : Acc export type TTemplateLiteralKeyRest = Assert>, TPropertyKey[]> @@ -1021,18 +990,18 @@ export interface TUndefined extends TSchema { // TUnionLiteral // -------------------------------------------------------------------------- // prettier-ignore -export type TLiteralUnionReduce[]> = - T extends [infer L, ...infer R] ? [Assert>['const'], ...TLiteralUnionReduce[]>>] : +export type TLiteralUnionReduce[]> = + T extends [infer L, ...infer R] ? [Assert>['const'], ...TLiteralUnionReduce[]>>] : [] // prettier-ignore -export type TUnionLiteralKeyRest[]>> = - T extends TUnion ? TLiteralUnionReduce[]>> : +export type TUnionLiteralKeyRest[]>> = + T extends TUnion ? TLiteralUnionReduce[]>> : [] // -------------------------------------------------------------------------- // TUnion // -------------------------------------------------------------------------- // prettier-ignore -export type TUnionTemplateLiteral> = Ensure}[S]>,TLiteral[]>>> +export type TUnionTemplateLiteral> = Ensure }[S]>, TLiteral[]>>> export interface TUnion extends TSchema { [Kind]: 'Union' static: { [K in keyof T]: T[K] extends TSchema ? Static : never }[number] @@ -1280,7 +1249,7 @@ export namespace TypeGuard { export function TAsyncIterator(schema: unknown): schema is TAsyncIterator { // prettier-ignore return ( - TKindOf(schema, 'AsyncIterator') && + TKindOf(schema, 'AsyncIterator') && schema.type === 'AsyncIterator' && IsOptionalString(schema.$id) && TSchema(schema.items) @@ -1290,22 +1259,22 @@ export namespace TypeGuard { export function TBigInt(schema: unknown): schema is TBigInt { // prettier-ignore return ( - TKindOf(schema, 'BigInt') && + TKindOf(schema, 'BigInt') && schema.type === 'bigint' && IsOptionalString(schema.$id) && IsOptionalBigInt(schema.exclusiveMaximum) && IsOptionalBigInt(schema.exclusiveMinimum) && IsOptionalBigInt(schema.maximum) && IsOptionalBigInt(schema.minimum) && - IsOptionalBigInt(schema.multipleOf) + IsOptionalBigInt(schema.multipleOf) ) } /** Returns true if the given value is TBoolean */ export function TBoolean(schema: unknown): schema is TBoolean { // prettier-ignore return ( - TKindOf(schema, 'Boolean') && - schema.type === 'boolean' && + TKindOf(schema, 'Boolean') && + schema.type === 'boolean' && IsOptionalString(schema.$id) ) } @@ -1313,9 +1282,9 @@ export namespace TypeGuard { export function TConstructor(schema: unknown): schema is TConstructor { // prettier-ignore return ( - TKindOf(schema, 'Constructor') && + TKindOf(schema, 'Constructor') && schema.type === 'Constructor' && - IsOptionalString(schema.$id) && + IsOptionalString(schema.$id) && ValueGuard.IsArray(schema.parameters) && schema.parameters.every(schema => TSchema(schema)) && TSchema(schema.returns) @@ -1340,8 +1309,8 @@ export namespace TypeGuard { return ( TKindOf(schema, 'Function') && schema.type === 'Function' && - IsOptionalString(schema.$id) && - ValueGuard.IsArray(schema.parameters) && + IsOptionalString(schema.$id) && + ValueGuard.IsArray(schema.parameters) && schema.parameters.every(schema => TSchema(schema)) && TSchema(schema.returns) ) @@ -1365,7 +1334,7 @@ export namespace TypeGuard { return ( TKindOf(schema, 'Intersect') && (ValueGuard.IsString(schema.type) && schema.type !== 'object' ? false : true) && - ValueGuard.IsArray(schema.allOf) && + ValueGuard.IsArray(schema.allOf) && schema.allOf.every(schema => TSchema(schema) && !TTransform(schema)) && IsOptionalString(schema.type) && (IsOptionalBoolean(schema.unevaluatedProperties) || IsOptionalSchema(schema.unevaluatedProperties)) && @@ -1419,7 +1388,7 @@ export namespace TypeGuard { // prettier-ignore return ( TKindOf(schema, 'Never') && - ValueGuard.IsObject(schema.not) && + ValueGuard.IsObject(schema.not) && Object.getOwnPropertyNames(schema.not).length === 0 ) } @@ -1428,7 +1397,7 @@ export namespace TypeGuard { // prettier-ignore return ( TKindOf(schema, 'Not') && - TSchema(schema.not) + TSchema(schema.not) ) } /** Returns true if the given value is TNull */ @@ -1436,7 +1405,7 @@ export namespace TypeGuard { // prettier-ignore return ( TKindOf(schema, 'Null') && - schema.type === 'null' && + schema.type === 'null' && IsOptionalString(schema.$id) ) } @@ -1473,7 +1442,7 @@ export namespace TypeGuard { return ( TKindOf(schema, 'Promise') && schema.type === 'Promise' && - IsOptionalString(schema.$id) && + IsOptionalString(schema.$id) && TSchema(schema.item) ) } @@ -1482,8 +1451,8 @@ export namespace TypeGuard { // prettier-ignore return ( TKindOf(schema, 'Record') && - schema.type === 'object' && - IsOptionalString(schema.$id) && + schema.type === 'object' && + IsOptionalString(schema.$id) && IsAdditionalProperties(schema.additionalProperties) && ValueGuard.IsObject(schema.patternProperties) && ((schema: Record) => { @@ -1506,7 +1475,7 @@ export namespace TypeGuard { // prettier-ignore return ( TKindOf(schema, 'Ref') && - IsOptionalString(schema.$id) && + IsOptionalString(schema.$id) && ValueGuard.IsString(schema.$ref) ) } @@ -1514,12 +1483,12 @@ export namespace TypeGuard { export function TString(schema: unknown): schema is TString { // prettier-ignore return ( - TKindOf(schema, 'String') && - schema.type === 'string' && - IsOptionalString(schema.$id) && - IsOptionalNumber(schema.minLength) && - IsOptionalNumber(schema.maxLength) && - IsOptionalPattern(schema.pattern) && + TKindOf(schema, 'String') && + schema.type === 'string' && + IsOptionalString(schema.$id) && + IsOptionalNumber(schema.minLength) && + IsOptionalNumber(schema.maxLength) && + IsOptionalPattern(schema.pattern) && IsOptionalFormat(schema.format) ) } @@ -1548,7 +1517,7 @@ export namespace TypeGuard { // prettier-ignore return ( TKindOf(schema, 'This') && - IsOptionalString(schema.$id) && + IsOptionalString(schema.$id) && ValueGuard.IsString(schema.$ref) ) } @@ -1561,19 +1530,19 @@ export namespace TypeGuard { // prettier-ignore return ( TKindOf(schema, 'Tuple') && - schema.type === 'array' && - IsOptionalString(schema.$id) && - ValueGuard.IsNumber(schema.minItems) && - ValueGuard.IsNumber(schema.maxItems) && + schema.type === 'array' && + IsOptionalString(schema.$id) && + ValueGuard.IsNumber(schema.minItems) && + ValueGuard.IsNumber(schema.maxItems) && schema.minItems === schema.maxItems && (( // empty ValueGuard.IsUndefined(schema.items) && ValueGuard.IsUndefined(schema.additionalItems) && schema.minItems === 0 ) || ( - ValueGuard.IsArray(schema.items) && - schema.items.every(schema => TSchema(schema)) - )) + ValueGuard.IsArray(schema.items) && + schema.items.every(schema => TSchema(schema)) + )) ) } /** Returns true if the given value is TUndefined */ @@ -1605,9 +1574,9 @@ export namespace TypeGuard { // prettier-ignore return ( TKindOf(schema, 'Uint8Array') && - schema.type === 'Uint8Array' && - IsOptionalString(schema.$id) && - IsOptionalNumber(schema.minByteLength) && + schema.type === 'Uint8Array' && + IsOptionalString(schema.$id) && + IsOptionalNumber(schema.minByteLength) && IsOptionalNumber(schema.maxByteLength) ) } @@ -1646,39 +1615,39 @@ export namespace TypeGuard { return ( ValueGuard.IsObject(schema) ) && ( - TAny(schema) || - TArray(schema) || - TBoolean(schema) || - TBigInt(schema) || - TAsyncIterator(schema) || - TConstructor(schema) || - TDate(schema) || - TFunction(schema) || - TInteger(schema) || - TIntersect(schema) || - TIterator(schema) || - TLiteral(schema) || - TNever(schema) || - TNot(schema) || - TNull(schema) || - TNumber(schema) || - TObject(schema) || - TPromise(schema) || - TRecord(schema) || - TRef(schema) || - TString(schema) || - TSymbol(schema) || - TTemplateLiteral(schema) || - TThis(schema) || - TTuple(schema) || - TUndefined(schema) || - TUnion(schema) || - TUint8Array(schema) || - TUnknown(schema) || - TUnsafe(schema) || - TVoid(schema) || - (TKind(schema) && TypeRegistry.Has(schema[Kind] as any)) - ) + TAny(schema) || + TArray(schema) || + TBoolean(schema) || + TBigInt(schema) || + TAsyncIterator(schema) || + TConstructor(schema) || + TDate(schema) || + TFunction(schema) || + TInteger(schema) || + TIntersect(schema) || + TIterator(schema) || + TLiteral(schema) || + TNever(schema) || + TNot(schema) || + TNull(schema) || + TNumber(schema) || + TObject(schema) || + TPromise(schema) || + TRecord(schema) || + TRef(schema) || + TString(schema) || + TSymbol(schema) || + TTemplateLiteral(schema) || + TThis(schema) || + TTuple(schema) || + TUndefined(schema) || + TUnion(schema) || + TUint8Array(schema) || + TUnknown(schema) || + TUnsafe(schema) || + TVoid(schema) || + (TKind(schema) && TypeRegistry.Has(schema[Kind] as any)) + ) } } // -------------------------------------------------------------------------- @@ -1726,10 +1695,10 @@ export namespace TypeExtends { function IsStructuralRight(right: TSchema): boolean { // prettier-ignore return ( - TypeGuard.TNever(right) || - TypeGuard.TIntersect(right) || - TypeGuard.TUnion(right) || - TypeGuard.TUnknown(right) || + TypeGuard.TNever(right) || + TypeGuard.TIntersect(right) || + TypeGuard.TUnion(right) || + TypeGuard.TUnknown(right) || TypeGuard.TAny(right) ) } @@ -1737,11 +1706,11 @@ export namespace TypeExtends { // prettier-ignore return ( TypeGuard.TNever(right) ? TNeverRight(left, right) : - TypeGuard.TIntersect(right) ? TIntersectRight(left, right) : - TypeGuard.TUnion(right) ? TUnionRight(left, right) : - TypeGuard.TUnknown(right) ? TUnknownRight(left, right) : - TypeGuard.TAny(right) ? TAnyRight(left, right) : - Throw('StructuralRight') + TypeGuard.TIntersect(right) ? TIntersectRight(left, right) : + TypeGuard.TUnion(right) ? TUnionRight(left, right) : + TypeGuard.TUnknown(right) ? TUnknownRight(left, right) : + TypeGuard.TAny(right) ? TAnyRight(left, right) : + Throw('StructuralRight') ) } // -------------------------------------------------------------------------- @@ -1754,11 +1723,11 @@ export namespace TypeExtends { // prettier-ignore return ( TypeGuard.TIntersect(right) ? TIntersectRight(left, right) : - (TypeGuard.TUnion(right) && right.anyOf.some((schema) => TypeGuard.TAny(schema) || TypeGuard.TUnknown(schema))) ? TypeExtendsResult.True : - TypeGuard.TUnion(right) ? TypeExtendsResult.Union : - TypeGuard.TUnknown(right) ? TypeExtendsResult.True : - TypeGuard.TAny(right) ? TypeExtendsResult.True : - TypeExtendsResult.Union + (TypeGuard.TUnion(right) && right.anyOf.some((schema) => TypeGuard.TAny(schema) || TypeGuard.TUnknown(schema))) ? TypeExtendsResult.True : + TypeGuard.TUnion(right) ? TypeExtendsResult.Union : + TypeGuard.TUnknown(right) ? TypeExtendsResult.True : + TypeGuard.TAny(right) ? TypeExtendsResult.True : + TypeExtendsResult.Union ) } // -------------------------------------------------------------------------- @@ -1768,18 +1737,18 @@ export namespace TypeExtends { // prettier-ignore return ( TypeGuard.TUnknown(left) ? TypeExtendsResult.False : - TypeGuard.TAny(left) ?TypeExtendsResult.Union : - TypeGuard.TNever(left) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TAny(left) ? TypeExtendsResult.Union : + TypeGuard.TNever(left) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } function TArray(left: TArray, right: TSchema) { // prettier-ignore return ( TypeGuard.TObject(right) && IsObjectArrayLike(right) ? TypeExtendsResult.True : - IsStructuralRight(right) ? StructuralRight(left, right) : - !TypeGuard.TArray(right) ? TypeExtendsResult.False : - IntoBooleanResult(Visit(left.items, right.items)) + IsStructuralRight(right) ? StructuralRight(left, right) : + !TypeGuard.TArray(right) ? TypeExtendsResult.False : + IntoBooleanResult(Visit(left.items, right.items)) ) } // -------------------------------------------------------------------------- @@ -1789,8 +1758,8 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - !TypeGuard.TAsyncIterator(right) ? TypeExtendsResult.False : - IntoBooleanResult(Visit(left.items, right.items)) + !TypeGuard.TAsyncIterator(right) ? TypeExtendsResult.False : + IntoBooleanResult(Visit(left.items, right.items)) ) } // -------------------------------------------------------------------------- @@ -1800,10 +1769,10 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeGuard.TBigInt(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeGuard.TBigInt(right) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -1816,10 +1785,10 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeGuard.TBoolean(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeGuard.TBoolean(right) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -1829,11 +1798,11 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - !TypeGuard.TConstructor(right) ? TypeExtendsResult.False : - left.parameters.length > right.parameters.length ? TypeExtendsResult.False : - (!left.parameters.every((schema, index) => IntoBooleanResult(Visit(right.parameters[index], schema)) === TypeExtendsResult.True)) ? TypeExtendsResult.False : - IntoBooleanResult(Visit(left.returns, right.returns)) + TypeGuard.TObject(right) ? TObjectRight(left, right) : + !TypeGuard.TConstructor(right) ? TypeExtendsResult.False : + left.parameters.length > right.parameters.length ? TypeExtendsResult.False : + (!left.parameters.every((schema, index) => IntoBooleanResult(Visit(right.parameters[index], schema)) === TypeExtendsResult.True)) ? TypeExtendsResult.False : + IntoBooleanResult(Visit(left.returns, right.returns)) ) } // -------------------------------------------------------------------------- @@ -1843,10 +1812,10 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeGuard.TDate(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeGuard.TDate(right) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -1856,11 +1825,11 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - !TypeGuard.TFunction(right) ? TypeExtendsResult.False : - left.parameters.length > right.parameters.length ? TypeExtendsResult.False : - (!left.parameters.every((schema, index) => IntoBooleanResult(Visit(right.parameters[index], schema)) === TypeExtendsResult.True)) ? TypeExtendsResult.False : - IntoBooleanResult(Visit(left.returns, right.returns)) + TypeGuard.TObject(right) ? TObjectRight(left, right) : + !TypeGuard.TFunction(right) ? TypeExtendsResult.False : + left.parameters.length > right.parameters.length ? TypeExtendsResult.False : + (!left.parameters.every((schema, index) => IntoBooleanResult(Visit(right.parameters[index], schema)) === TypeExtendsResult.True)) ? TypeExtendsResult.False : + IntoBooleanResult(Visit(left.returns, right.returns)) ) } // -------------------------------------------------------------------------- @@ -1870,18 +1839,18 @@ export namespace TypeExtends { // prettier-ignore return ( TypeGuard.TLiteral(left) && ValueGuard.IsNumber(left.const) ? TypeExtendsResult.True : - TypeGuard.TNumber(left) || TypeGuard.TInteger(left) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TNumber(left) || TypeGuard.TInteger(left) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } function TInteger(left: TInteger, right: TSchema): TypeExtendsResult { // prettier-ignore return ( - TypeGuard.TInteger(right) || TypeGuard.TNumber(right) ? TypeExtendsResult.True : - IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeExtendsResult.False + TypeGuard.TInteger(right) || TypeGuard.TNumber(right) ? TypeExtendsResult.True : + IsStructuralRight(right) ? StructuralRight(left, right) : + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -1889,14 +1858,14 @@ export namespace TypeExtends { // -------------------------------------------------------------------------- function TIntersectRight(left: TSchema, right: TIntersect): TypeExtendsResult { // prettier-ignore - return right.allOf.every((schema) => Visit(left, schema) === TypeExtendsResult.True) - ? TypeExtendsResult.True + return right.allOf.every((schema) => Visit(left, schema) === TypeExtendsResult.True) + ? TypeExtendsResult.True : TypeExtendsResult.False } function TIntersect(left: TIntersect, right: TSchema) { // prettier-ignore - return left.allOf.some((schema) => Visit(schema, right) === TypeExtendsResult.True) - ? TypeExtendsResult.True + return left.allOf.some((schema) => Visit(schema, right) === TypeExtendsResult.True) + ? TypeExtendsResult.True : TypeExtendsResult.False } // -------------------------------------------------------------------------- @@ -1906,8 +1875,8 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - !TypeGuard.TIterator(right) ? TypeExtendsResult.False : - IntoBooleanResult(Visit(left.items, right.items)) + !TypeGuard.TIterator(right) ? TypeExtendsResult.False : + IntoBooleanResult(Visit(left.items, right.items)) ) } // -------------------------------------------------------------------------- @@ -1916,15 +1885,15 @@ export namespace TypeExtends { function TLiteral(left: TLiteral, right: TSchema): TypeExtendsResult { // prettier-ignore return ( - TypeGuard.TLiteral(right) && right.const === left.const ? TypeExtendsResult.True : - IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeGuard.TString(right) ? TStringRight(left, right) : - TypeGuard.TNumber(right) ? TNumberRight(left, right) : - TypeGuard.TInteger(right) ? TIntegerRight(left, right) : - TypeGuard.TBoolean(right) ? TBooleanRight(left, right) : - TypeExtendsResult.False + TypeGuard.TLiteral(right) && right.const === left.const ? TypeExtendsResult.True : + IsStructuralRight(right) ? StructuralRight(left, right) : + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeGuard.TString(right) ? TStringRight(left, right) : + TypeGuard.TNumber(right) ? TNumberRight(left, right) : + TypeGuard.TInteger(right) ? TIntegerRight(left, right) : + TypeGuard.TBoolean(right) ? TBooleanRight(left, right) : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -1955,8 +1924,8 @@ export namespace TypeExtends { // prettier-ignore return ( TypeGuard.TNot(left) ? Visit(UnwrapTNot(left), right) : - TypeGuard.TNot(right) ? Visit(left, UnwrapTNot(right)) : - Throw('Invalid fallthrough for Not') + TypeGuard.TNot(right) ? Visit(left, UnwrapTNot(right)) : + Throw('Invalid fallthrough for Not') ) } // -------------------------------------------------------------------------- @@ -1966,10 +1935,10 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeGuard.TNull(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeGuard.TNull(right) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -1979,18 +1948,18 @@ export namespace TypeExtends { // prettier-ignore return ( TypeGuard.TLiteralNumber(left) ? TypeExtendsResult.True : - TypeGuard.TNumber(left) || TypeGuard.TInteger(left) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TNumber(left) || TypeGuard.TInteger(left) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } function TNumber(left: TNumber, right: TSchema): TypeExtendsResult { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeGuard.TInteger(right) || TypeGuard.TNumber(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeGuard.TInteger(right) || TypeGuard.TNumber(right) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -2009,9 +1978,9 @@ export namespace TypeExtends { TypeGuard.TString(schema.properties.description.anyOf[0]) && TypeGuard.TUndefined(schema.properties.description.anyOf[1]) ) || ( - TypeGuard.TString(schema.properties.description.anyOf[1]) && - TypeGuard.TUndefined(schema.properties.description.anyOf[0]) - )) + TypeGuard.TString(schema.properties.description.anyOf[1]) && + TypeGuard.TUndefined(schema.properties.description.anyOf[0]) + )) ) } function IsObjectNumberLike(schema: TObject) { @@ -2051,64 +2020,64 @@ export namespace TypeExtends { // prettier-ignore return ( Visit(left, right) === TypeExtendsResult.False ? TypeExtendsResult.False : - TypeGuard.TOptional(left) && !TypeGuard.TOptional(right) ? TypeExtendsResult.False : - TypeExtendsResult.True + TypeGuard.TOptional(left) && !TypeGuard.TOptional(right) ? TypeExtendsResult.False : + TypeExtendsResult.True ) } function TObjectRight(left: TSchema, right: TObject) { // prettier-ignore return ( TypeGuard.TUnknown(left) ? TypeExtendsResult.False : - TypeGuard.TAny(left) ? TypeExtendsResult.Union : ( - TypeGuard.TNever(left) || - (TypeGuard.TLiteralString(left) && IsObjectStringLike(right)) || - (TypeGuard.TLiteralNumber(left) && IsObjectNumberLike(right)) || - (TypeGuard.TLiteralBoolean(left) && IsObjectBooleanLike(right)) || - (TypeGuard.TSymbol(left) && IsObjectSymbolLike(right)) || - (TypeGuard.TBigInt(left) && IsObjectBigIntLike(right)) || - (TypeGuard.TString(left) && IsObjectStringLike(right)) || - (TypeGuard.TSymbol(left) && IsObjectSymbolLike(right)) || - (TypeGuard.TNumber(left) && IsObjectNumberLike(right)) || - (TypeGuard.TInteger(left) && IsObjectNumberLike(right)) || - (TypeGuard.TBoolean(left) && IsObjectBooleanLike(right)) || - (TypeGuard.TUint8Array(left) && IsObjectUint8ArrayLike(right)) || - (TypeGuard.TDate(left) && IsObjectDateLike(right)) || - (TypeGuard.TConstructor(left) && IsObjectConstructorLike(right)) || - (TypeGuard.TFunction(left) && IsObjectFunctionLike(right)) - ) ? TypeExtendsResult.True : - (TypeGuard.TRecord(left) && TypeGuard.TString(RecordKey(left))) ? (() => { - // When expressing a Record with literal key values, the Record is converted into a Object with - // the Hint assigned as `Record`. This is used to invert the extends logic. - return right[Hint] === 'Record' ? TypeExtendsResult.True : TypeExtendsResult.False - })() : - (TypeGuard.TRecord(left) && TypeGuard.TNumber(RecordKey(left))) ? (() => { - return IsObjectPropertyCount(right, 0) - ? TypeExtendsResult.True - : TypeExtendsResult.False - })() : - TypeExtendsResult.False + TypeGuard.TAny(left) ? TypeExtendsResult.Union : ( + TypeGuard.TNever(left) || + (TypeGuard.TLiteralString(left) && IsObjectStringLike(right)) || + (TypeGuard.TLiteralNumber(left) && IsObjectNumberLike(right)) || + (TypeGuard.TLiteralBoolean(left) && IsObjectBooleanLike(right)) || + (TypeGuard.TSymbol(left) && IsObjectSymbolLike(right)) || + (TypeGuard.TBigInt(left) && IsObjectBigIntLike(right)) || + (TypeGuard.TString(left) && IsObjectStringLike(right)) || + (TypeGuard.TSymbol(left) && IsObjectSymbolLike(right)) || + (TypeGuard.TNumber(left) && IsObjectNumberLike(right)) || + (TypeGuard.TInteger(left) && IsObjectNumberLike(right)) || + (TypeGuard.TBoolean(left) && IsObjectBooleanLike(right)) || + (TypeGuard.TUint8Array(left) && IsObjectUint8ArrayLike(right)) || + (TypeGuard.TDate(left) && IsObjectDateLike(right)) || + (TypeGuard.TConstructor(left) && IsObjectConstructorLike(right)) || + (TypeGuard.TFunction(left) && IsObjectFunctionLike(right)) + ) ? TypeExtendsResult.True : + (TypeGuard.TRecord(left) && TypeGuard.TString(RecordKey(left))) ? (() => { + // When expressing a Record with literal key values, the Record is converted into a Object with + // the Hint assigned as `Record`. This is used to invert the extends logic. + return right[Hint] === 'Record' ? TypeExtendsResult.True : TypeExtendsResult.False + })() : + (TypeGuard.TRecord(left) && TypeGuard.TNumber(RecordKey(left))) ? (() => { + return IsObjectPropertyCount(right, 0) + ? TypeExtendsResult.True + : TypeExtendsResult.False + })() : + TypeExtendsResult.False ) } function TObject(left: TObject, right: TSchema) { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - !TypeGuard.TObject(right) ? TypeExtendsResult.False : - (() => { - for (const key of Object.getOwnPropertyNames(right.properties)) { - if (!(key in left.properties) && !TypeGuard.TOptional(right.properties[key])) { - return TypeExtendsResult.False - } - if(TypeGuard.TOptional(right.properties[key])) { - return TypeExtendsResult.True - } - if (Property(left.properties[key], right.properties[key]) === TypeExtendsResult.False) { - return TypeExtendsResult.False - } - } - return TypeExtendsResult.True - })() + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + !TypeGuard.TObject(right) ? TypeExtendsResult.False : + (() => { + for (const key of Object.getOwnPropertyNames(right.properties)) { + if (!(key in left.properties) && !TypeGuard.TOptional(right.properties[key])) { + return TypeExtendsResult.False + } + if (TypeGuard.TOptional(right.properties[key])) { + return TypeExtendsResult.True + } + if (Property(left.properties[key], right.properties[key]) === TypeExtendsResult.False) { + return TypeExtendsResult.False + } + } + return TypeExtendsResult.True + })() ) } // -------------------------------------------------------------------------- @@ -2118,9 +2087,9 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) && IsObjectPromiseLike(right) ? TypeExtendsResult.True : - !TypeGuard.TPromise(right) ? TypeExtendsResult.False : - IntoBooleanResult(Visit(left.item, right.item)) + TypeGuard.TObject(right) && IsObjectPromiseLike(right) ? TypeExtendsResult.True : + !TypeGuard.TPromise(right) ? TypeExtendsResult.False : + IntoBooleanResult(Visit(left.item, right.item)) ) } // -------------------------------------------------------------------------- @@ -2130,16 +2099,16 @@ export namespace TypeExtends { // prettier-ignore return ( PatternNumberExact in schema.patternProperties ? Type.Number() : - PatternStringExact in schema.patternProperties ? Type.String() : - Throw('Unknown record key pattern') + PatternStringExact in schema.patternProperties ? Type.String() : + Throw('Unknown record key pattern') ) } function RecordValue(schema: TRecord) { // prettier-ignore return ( PatternNumberExact in schema.patternProperties ? schema.patternProperties[PatternNumberExact] : - PatternStringExact in schema.patternProperties ? schema.patternProperties[PatternStringExact] : - Throw('Unable to get record value schema') + PatternStringExact in schema.patternProperties ? schema.patternProperties[PatternStringExact] : + Throw('Unable to get record value schema') ) } function TRecordRight(left: TSchema, right: TRecord) { @@ -2147,27 +2116,27 @@ export namespace TypeExtends { // prettier-ignore return ( (TypeGuard.TLiteralString(left) && TypeGuard.TNumber(Key) && IntoBooleanResult(Visit(left, Value)) === TypeExtendsResult.True) ? TypeExtendsResult.True : - TypeGuard.TUint8Array(left) && TypeGuard.TNumber(Key) ? Visit(left, Value) : - TypeGuard.TString(left) && TypeGuard.TNumber(Key) ? Visit(left, Value) : - TypeGuard.TArray(left) && TypeGuard.TNumber(Key) ? Visit(left, Value) : - TypeGuard.TObject(left) ? (() => { - for (const key of Object.getOwnPropertyNames(left.properties)) { - if (Property(Value, left.properties[key]) === TypeExtendsResult.False) { - return TypeExtendsResult.False - } - } - return TypeExtendsResult.True - })() : - TypeExtendsResult.False + TypeGuard.TUint8Array(left) && TypeGuard.TNumber(Key) ? Visit(left, Value) : + TypeGuard.TString(left) && TypeGuard.TNumber(Key) ? Visit(left, Value) : + TypeGuard.TArray(left) && TypeGuard.TNumber(Key) ? Visit(left, Value) : + TypeGuard.TObject(left) ? (() => { + for (const key of Object.getOwnPropertyNames(left.properties)) { + if (Property(Value, left.properties[key]) === TypeExtendsResult.False) { + return TypeExtendsResult.False + } + } + return TypeExtendsResult.True + })() : + TypeExtendsResult.False ) } function TRecord(left: TRecord, right: TSchema) { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - !TypeGuard.TRecord(right) ? TypeExtendsResult.False : - Visit(RecordValue(left), RecordValue(right)) + TypeGuard.TObject(right) ? TObjectRight(left, right) : + !TypeGuard.TRecord(right) ? TypeExtendsResult.False : + Visit(RecordValue(left), RecordValue(right)) ) } // -------------------------------------------------------------------------- @@ -2177,18 +2146,18 @@ export namespace TypeExtends { // prettier-ignore return ( TypeGuard.TLiteral(left) && ValueGuard.IsString(left.const) ? TypeExtendsResult.True : - TypeGuard.TString(left) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TString(left) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } function TString(left: TString, right: TSchema): TypeExtendsResult { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeGuard.TString(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeGuard.TString(right) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -2198,10 +2167,10 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeGuard.TSymbol(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeGuard.TSymbol(right) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -2214,8 +2183,8 @@ export namespace TypeExtends { // prettier-ignore return ( TypeGuard.TTemplateLiteral(left) ? Visit(TemplateLiteralResolver.Resolve(left), right) : - TypeGuard.TTemplateLiteral(right) ? Visit(left, TemplateLiteralResolver.Resolve(right)) : - Throw('Invalid fallthrough for TemplateLiteral') + TypeGuard.TTemplateLiteral(right) ? Visit(left, TemplateLiteralResolver.Resolve(right)) : + Throw('Invalid fallthrough for TemplateLiteral') ) } // -------------------------------------------------------------------------- @@ -2224,8 +2193,8 @@ export namespace TypeExtends { function IsArrayOfTuple(left: TTuple, right: TSchema) { // prettier-ignore return ( - TypeGuard.TArray(right) && - left.items !== undefined && + TypeGuard.TArray(right) && + left.items !== undefined && left.items.every((schema) => Visit(schema, right.items) === TypeExtendsResult.True) ) } @@ -2233,22 +2202,22 @@ export namespace TypeExtends { // prettier-ignore return ( TypeGuard.TNever(left) ? TypeExtendsResult.True : - TypeGuard.TUnknown(left) ? TypeExtendsResult.False : - TypeGuard.TAny(left) ? TypeExtendsResult.Union : - TypeExtendsResult.False + TypeGuard.TUnknown(left) ? TypeExtendsResult.False : + TypeGuard.TAny(left) ? TypeExtendsResult.Union : + TypeExtendsResult.False ) } function TTuple(left: TTuple, right: TSchema): TypeExtendsResult { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) && IsObjectArrayLike(right) ? TypeExtendsResult.True : - TypeGuard.TArray(right) && IsArrayOfTuple(left, right) ? TypeExtendsResult.True : - !TypeGuard.TTuple(right) ? TypeExtendsResult.False : - (ValueGuard.IsUndefined(left.items) && !ValueGuard.IsUndefined(right.items)) || (!ValueGuard.IsUndefined(left.items) && ValueGuard.IsUndefined(right.items)) ? TypeExtendsResult.False : - (ValueGuard.IsUndefined(left.items) && !ValueGuard.IsUndefined(right.items)) ? TypeExtendsResult.True : - left.items!.every((schema, index) => Visit(schema, right.items![index]) === TypeExtendsResult.True) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TObject(right) && IsObjectArrayLike(right) ? TypeExtendsResult.True : + TypeGuard.TArray(right) && IsArrayOfTuple(left, right) ? TypeExtendsResult.True : + !TypeGuard.TTuple(right) ? TypeExtendsResult.False : + (ValueGuard.IsUndefined(left.items) && !ValueGuard.IsUndefined(right.items)) || (!ValueGuard.IsUndefined(left.items) && ValueGuard.IsUndefined(right.items)) ? TypeExtendsResult.False : + (ValueGuard.IsUndefined(left.items) && !ValueGuard.IsUndefined(right.items)) ? TypeExtendsResult.True : + left.items!.every((schema, index) => Visit(schema, right.items![index]) === TypeExtendsResult.True) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -2258,10 +2227,10 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeGuard.TUint8Array(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeGuard.TUint8Array(right) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -2271,11 +2240,11 @@ export namespace TypeExtends { // prettier-ignore return ( IsStructuralRight(right) ? StructuralRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TRecord(right) ? TRecordRight(left, right) : - TypeGuard.TVoid(right) ? VoidRight(left, right) : - TypeGuard.TUndefined(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TRecord(right) ? TRecordRight(left, right) : + TypeGuard.TVoid(right) ? VoidRight(left, right) : + TypeGuard.TUndefined(right) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -2283,14 +2252,14 @@ export namespace TypeExtends { // -------------------------------------------------------------------------- function TUnionRight(left: TSchema, right: TUnion): TypeExtendsResult { // prettier-ignore - return right.anyOf.some((schema) => Visit(left, schema) === TypeExtendsResult.True) - ? TypeExtendsResult.True + return right.anyOf.some((schema) => Visit(left, schema) === TypeExtendsResult.True) + ? TypeExtendsResult.True : TypeExtendsResult.False } function TUnion(left: TUnion, right: TSchema): TypeExtendsResult { // prettier-ignore - return left.anyOf.every((schema) => Visit(schema, right) === TypeExtendsResult.True) - ? TypeExtendsResult.True + return left.anyOf.every((schema) => Visit(schema, right) === TypeExtendsResult.True) + ? TypeExtendsResult.True : TypeExtendsResult.False } // -------------------------------------------------------------------------- @@ -2303,18 +2272,18 @@ export namespace TypeExtends { // prettier-ignore return ( TypeGuard.TNever(right) ? TNeverRight(left, right) : - TypeGuard.TIntersect(right) ? TIntersectRight(left, right) : - TypeGuard.TUnion(right) ? TUnionRight(left, right) : - TypeGuard.TAny(right) ? TAnyRight(left, right) : - TypeGuard.TString(right) ? TStringRight(left, right) : - TypeGuard.TNumber(right) ? TNumberRight(left, right) : - TypeGuard.TInteger(right) ? TIntegerRight(left, right) : - TypeGuard.TBoolean(right) ? TBooleanRight(left, right) : - TypeGuard.TArray(right) ? TArrayRight(left, right) : - TypeGuard.TTuple(right) ? TTupleRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TUnknown(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TIntersect(right) ? TIntersectRight(left, right) : + TypeGuard.TUnion(right) ? TUnionRight(left, right) : + TypeGuard.TAny(right) ? TAnyRight(left, right) : + TypeGuard.TString(right) ? TStringRight(left, right) : + TypeGuard.TNumber(right) ? TNumberRight(left, right) : + TypeGuard.TInteger(right) ? TIntegerRight(left, right) : + TypeGuard.TBoolean(right) ? TBooleanRight(left, right) : + TypeGuard.TArray(right) ? TArrayRight(left, right) : + TypeGuard.TTuple(right) ? TTupleRight(left, right) : + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TUnknown(right) ? TypeExtendsResult.True : + TypeExtendsResult.False ) } // -------------------------------------------------------------------------- @@ -2323,53 +2292,53 @@ export namespace TypeExtends { function VoidRight(left: TSchema, right: TVoid) { // prettier-ignore return TypeGuard.TUndefined(left) ? TypeExtendsResult.True : - TypeGuard.TUndefined(left) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TUndefined(left) ? TypeExtendsResult.True : + TypeExtendsResult.False } function TVoid(left: TVoid, right: TSchema) { // prettier-ignore return TypeGuard.TIntersect(right) ? TIntersectRight(left, right) : TypeGuard.TUnion(right) ? TUnionRight(left, right) : - TypeGuard.TUnknown(right) ? TUnknownRight(left, right) : - TypeGuard.TAny(right) ? TAnyRight(left, right) : - TypeGuard.TObject(right) ? TObjectRight(left, right) : - TypeGuard.TVoid(right) ? TypeExtendsResult.True : - TypeExtendsResult.False + TypeGuard.TUnknown(right) ? TUnknownRight(left, right) : + TypeGuard.TAny(right) ? TAnyRight(left, right) : + TypeGuard.TObject(right) ? TObjectRight(left, right) : + TypeGuard.TVoid(right) ? TypeExtendsResult.True : + TypeExtendsResult.False } function Visit(left: TSchema, right: TSchema): TypeExtendsResult { // prettier-ignore return ( // resolvable (TypeGuard.TTemplateLiteral(left) || TypeGuard.TTemplateLiteral(right)) ? TTemplateLiteral(left, right) : - (TypeGuard.TNot(left) || TypeGuard.TNot(right)) ? TNot(left, right) : - // standard - TypeGuard.TAny(left) ? TAny(left, right) : - TypeGuard.TArray(left) ? TArray(left, right) : - TypeGuard.TBigInt(left) ? TBigInt(left, right) : - TypeGuard.TBoolean(left) ? TBoolean(left, right) : - TypeGuard.TAsyncIterator(left) ? TAsyncIterator(left, right) : - TypeGuard.TConstructor(left) ? TConstructor(left, right) : - TypeGuard.TDate(left) ? TDate(left, right) : - TypeGuard.TFunction(left) ? TFunction(left, right) : - TypeGuard.TInteger(left) ? TInteger(left, right) : - TypeGuard.TIntersect(left) ? TIntersect(left, right) : - TypeGuard.TIterator(left) ? TIterator(left, right) : - TypeGuard.TLiteral(left) ? TLiteral(left, right) : - TypeGuard.TNever(left) ? TNever(left, right) : - TypeGuard.TNull(left) ? TNull(left, right) : - TypeGuard.TNumber(left) ? TNumber(left, right) : - TypeGuard.TObject(left) ? TObject(left, right) : - TypeGuard.TRecord(left) ? TRecord(left, right) : - TypeGuard.TString(left) ? TString(left, right) : - TypeGuard.TSymbol(left) ? TSymbol(left, right) : - TypeGuard.TTuple(left) ? TTuple(left, right) : - TypeGuard.TPromise(left) ? TPromise(left, right) : - TypeGuard.TUint8Array(left) ? TUint8Array(left, right) : - TypeGuard.TUndefined(left) ? TUndefined(left, right) : - TypeGuard.TUnion(left) ? TUnion(left, right) : - TypeGuard.TUnknown(left) ? TUnknown(left, right) : - TypeGuard.TVoid(left) ? TVoid(left, right) : - Throw(`Unknown left type operand '${left[Kind]}'`) + (TypeGuard.TNot(left) || TypeGuard.TNot(right)) ? TNot(left, right) : + // standard + TypeGuard.TAny(left) ? TAny(left, right) : + TypeGuard.TArray(left) ? TArray(left, right) : + TypeGuard.TBigInt(left) ? TBigInt(left, right) : + TypeGuard.TBoolean(left) ? TBoolean(left, right) : + TypeGuard.TAsyncIterator(left) ? TAsyncIterator(left, right) : + TypeGuard.TConstructor(left) ? TConstructor(left, right) : + TypeGuard.TDate(left) ? TDate(left, right) : + TypeGuard.TFunction(left) ? TFunction(left, right) : + TypeGuard.TInteger(left) ? TInteger(left, right) : + TypeGuard.TIntersect(left) ? TIntersect(left, right) : + TypeGuard.TIterator(left) ? TIterator(left, right) : + TypeGuard.TLiteral(left) ? TLiteral(left, right) : + TypeGuard.TNever(left) ? TNever(left, right) : + TypeGuard.TNull(left) ? TNull(left, right) : + TypeGuard.TNumber(left) ? TNumber(left, right) : + TypeGuard.TObject(left) ? TObject(left, right) : + TypeGuard.TRecord(left) ? TRecord(left, right) : + TypeGuard.TString(left) ? TString(left, right) : + TypeGuard.TSymbol(left) ? TSymbol(left, right) : + TypeGuard.TTuple(left) ? TTuple(left, right) : + TypeGuard.TPromise(left) ? TPromise(left, right) : + TypeGuard.TUint8Array(left) ? TUint8Array(left, right) : + TypeGuard.TUndefined(left) ? TUndefined(left, right) : + TypeGuard.TUnion(left) ? TUnion(left, right) : + TypeGuard.TUnknown(left) ? TUnknown(left, right) : + TypeGuard.TVoid(left) ? TVoid(left, right) : + Throw(`Unknown left type operand '${left[Kind]}'`) ) } export function Extends(left: TSchema, right: TSchema): TypeExtendsResult { @@ -2399,10 +2368,10 @@ export namespace TypeClone { // prettier-ignore return ( ValueGuard.IsArray(value) ? ArrayType(value) : - ValueGuard.IsDate(value) ? DateType(value) : - ValueGuard.IsUint8Array(value) ? Uint8ArrayType(value) : - ValueGuard.IsObject(value) ? ObjectType(value) : - value + ValueGuard.IsDate(value) ? DateType(value) : + ValueGuard.IsUint8Array(value) ? Uint8ArrayType(value) : + ValueGuard.IsObject(value) ? ObjectType(value) : + value ) } /** Clones a Rest */ @@ -2432,69 +2401,6 @@ export namespace DistinctRest { } } -// -------------------------------------------------------------------------- -// IndexedAccessor -// -------------------------------------------------------------------------- -export namespace IndexedAccessor { - function OptionalUnwrap(schema: TSchema[]): TSchema[] { - return schema.map((schema) => { - const { [Optional]: _, ...clone } = TypeClone.Type(schema) - return clone - }) - } - function IsIntersectOptional(schema: TSchema[]): boolean { - return schema.every((schema) => TypeGuard.TOptional(schema)) - } - function IsUnionOptional(schema: TSchema[]): boolean { - return schema.some((schema) => TypeGuard.TOptional(schema)) - } - function ResolveIntersect(schema: TIntersect): TSchema { - return IsIntersectOptional(schema.allOf) ? Type.Optional(Type.Intersect(OptionalUnwrap(schema.allOf))) : schema - } - function ResolveUnion(schema: TUnion): TSchema { - return IsUnionOptional(schema.anyOf) ? Type.Optional(Type.Union(OptionalUnwrap(schema.anyOf))) : schema - } - function ResolveOptional(schema: TSchema) { - // prettier-ignore - return schema[Kind] === 'Intersect' ? ResolveIntersect(schema as TIntersect) : - schema[Kind] === 'Union' ? ResolveUnion(schema as TUnion) : - schema - } - function TIntersect(schema: TIntersect, key: string): TSchema { - const resolved = schema.allOf.reduce((acc, schema) => { - const indexed = Visit(schema, key) - return indexed[Kind] === 'Never' ? acc : [...acc, indexed] - }, [] as TSchema[]) - return ResolveOptional(Type.Intersect(resolved)) - } - function TUnion(schema: TUnion, key: string): TSchema { - const resolved = schema.anyOf.map((schema) => Visit(schema, key)) - return ResolveOptional(Type.Union(resolved)) - } - function TObject(schema: TObject, key: string): TSchema { - const property = schema.properties[key] - return ValueGuard.IsUndefined(property) ? Type.Never() : Type.Union([property]) - } - function TTuple(schema: TTuple, key: string): TSchema { - const items = schema.items - if (ValueGuard.IsUndefined(items)) return Type.Never() - const element = items[key as any as number] // - if (ValueGuard.IsUndefined(element)) return Type.Never() - return element - } - function Visit(schema: TSchema, key: string): TSchema { - // prettier-ignore - return schema[Kind] === 'Intersect' ? TIntersect(schema as TIntersect, key) : - schema[Kind] === 'Union' ? TUnion(schema as TUnion, key) : - schema[Kind] === 'Object' ? TObject(schema as TObject, key) : - schema[Kind] === 'Tuple' ? TTuple(schema as TTuple, key) : - Type.Never() - } - export function Resolve(schema: TSchema, keys: TPropertyKey[], options: SchemaOptions = {}): TSchema { - const resolved = keys.map((key) => Visit(schema, key.toString())) - return ResolveOptional(Type.Union(resolved, options)) - } -} // -------------------------------------------------------------------------- // Intrinsic // -------------------------------------------------------------------------- @@ -2529,10 +2435,10 @@ export namespace Intrinsic { // prettier-ignore return typeof value === 'string' ? ( mode === 'Uncapitalize' ? Uncapitalize(value) : - mode === 'Capitalize' ? Capitalize(value) : - mode === 'Uppercase' ? Uppercase(value) : - mode === 'Lowercase' ? Lowercase(value) : - value) : value.toString() + mode === 'Capitalize' ? Capitalize(value) : + mode === 'Uppercase' ? Uppercase(value) : + mode === 'Lowercase' ? Lowercase(value) : + value) : value.toString() } function IntrinsicRest(schema: TSchema[], mode: TIntrinsicMode): TSchema[] { if (schema.length === 0) return [] @@ -2541,10 +2447,10 @@ export namespace Intrinsic { } function Visit(schema: TSchema, mode: TIntrinsicMode) { // prettier-ignore - return TypeGuard.TTemplateLiteral(schema) ? IntrinsicTemplateLiteral(schema, mode) : + return TypeGuard.TTemplateLiteral(schema) ? IntrinsicTemplateLiteral(schema, mode) : TypeGuard.TUnion(schema) ? Type.Union(IntrinsicRest(schema.anyOf, mode)) : - TypeGuard.TLiteral(schema) ? Type.Literal(IntrinsicLiteral(schema.const, mode)) : - schema + TypeGuard.TLiteral(schema) ? Type.Literal(IntrinsicLiteral(schema.const, mode)) : + schema } /** Applies an intrinsic string manipulation to the given type. */ export function Map(schema: T, mode: M): TIntrinsic { @@ -2554,13 +2460,12 @@ export namespace Intrinsic { // -------------------------------------------------------------------------- // ObjectMap // -------------------------------------------------------------------------- +// prettier-ignore export namespace ObjectMap { function TIntersect(schema: TIntersect, callback: (object: TObject) => TObject) { - // prettier-ignore return Type.Intersect(schema.allOf.map((inner) => Visit(inner, callback)), { ...schema }) } function TUnion(schema: TUnion, callback: (object: TObject) => TObject) { - // prettier-ignore return Type.Union(schema.anyOf.map((inner) => Visit(inner, callback)), { ...schema }) } function TObject(schema: TObject, callback: (object: TObject) => TObject) { @@ -2571,29 +2476,29 @@ export namespace ObjectMap { // prevent sub schema mapping as unregistered kinds will not pass TSchema checks. This is notable in the // case of TObject where unregistered property kinds cause the TObject check to fail. As mapping is only // used for composition, we use explicit checks instead. - // prettier-ignore - return ( - schema[Kind] === 'Intersect' ? TIntersect(schema as TIntersect, callback) : - schema[Kind] === 'Union' ? TUnion(schema as TUnion, callback) : - schema[Kind] === 'Object' ? TObject(schema as TObject, callback) : - schema - ) + switch (true) { + case schema[Kind] === 'Intersect': return TIntersect(schema as TIntersect, callback) + case schema[Kind] === 'Union': return TUnion(schema as TUnion, callback) + case schema[Kind] === 'Object': return TObject(schema as TObject, callback) + default: return schema + } } export function Map(schema: TSchema, callback: (object: TObject) => TObject, options: SchemaOptions): T { return { ...Visit(TypeClone.Type(schema), callback), ...options } as unknown as T } } // -------------------------------------------------------------------------- -// KeyResolver +// Indexer // -------------------------------------------------------------------------- -export interface KeyResolverOptions { +export interface IndexerOptions { includePatterns: boolean } -export namespace KeyResolver { +// prettier-ignore +export namespace Indexer { function UnwrapPattern(key: string) { return key[0] === '^' && key[key.length - 1] === '$' ? key.slice(1, key.length - 1) : key } - function TTemplateLiteral(schema: TTemplateLiteral, options: KeyResolverOptions): string[] { + function TTemplateLiteral(schema: TTemplateLiteral, options: IndexerOptions): string[] { const expression = TemplateLiteralParser.ParseExact(schema.pattern) const finite = TemplateLiteralFinite.Check(expression) if (!finite && options.includePatterns) return [schema.pattern] @@ -2601,57 +2506,131 @@ export namespace KeyResolver { const resolved = TemplateLiteralResolver.Resolve(schema) return TypeGuard.TUnionLiteral(resolved) ? resolved.anyOf.map((schema) => schema.const.toString()) : [] } - function TIntersect(schema: TIntersect, options: KeyResolverOptions): string[] { + function TIntersect(schema: TIntersect, options: IndexerOptions): string[] { return schema.allOf.reduce((acc, schema) => [...acc, ...Visit(schema, options)], [] as string[]) } - function TUnion(schema: TUnion, options: KeyResolverOptions): string[] { + function TUnion(schema: TUnion, options: IndexerOptions): string[] { const sets = schema.anyOf.map((inner) => Visit(inner, options)) return [...sets.reduce((set, outer) => outer.map((key) => (sets.every((inner) => inner.includes(key)) ? set.add(key) : set))[0], new Set())] } - function TObject(schema: TObject, options: KeyResolverOptions): string[] { + function TObject(schema: TObject, options: IndexerOptions): string[] { return Object.getOwnPropertyNames(schema.properties) } - function TRecord(schema: TRecord, options: KeyResolverOptions): string[] { + function TRecord(schema: TRecord, options: IndexerOptions): string[] { return options.includePatterns ? Object.getOwnPropertyNames(schema.patternProperties) : [] } - function Visit(schema: TSchema, options: KeyResolverOptions): string[] { - // prettier-ignore - return ( - TypeGuard.TTemplateLiteral(schema) ? TTemplateLiteral(schema, options) : - TypeGuard.TIntersect(schema) ? TIntersect(schema, options) : - TypeGuard.TUnion(schema) ? TUnion(schema, options) : - TypeGuard.TObject(schema) ? TObject(schema, options) : - TypeGuard.TRecord(schema) ? TRecord(schema, options) : - [] - ) - } - /** Resolves an array of keys in this schema */ - export function ResolveKeys(schema: TSchema, options: KeyResolverOptions): string[] { - return [...new Set(Visit(schema, options))] + function TNumber(schema: TNumber, options: IndexerOptions): string[] { + return ['number'] + } + function TInteger(schema: TInteger, options: IndexerOptions): string[] { + return ['number'] + } + function Visit(schema: TSchema, options: IndexerOptions): string[] { + switch (true) { + case TypeGuard.TTemplateLiteral(schema): return TTemplateLiteral(schema, options) + case TypeGuard.TIntersect(schema): return TIntersect(schema, options) + case TypeGuard.TUnion(schema): return TUnion(schema, options) + case TypeGuard.TObject(schema): return TObject(schema, options) + case TypeGuard.TRecord(schema): return TRecord(schema, options) + case TypeGuard.TInteger(schema): return TInteger(schema, options) + case TypeGuard.TNumber(schema): return TNumber(schema, options) + default: return [] + } } /** Resolves a regular expression pattern matching all keys in this schema */ - export function ResolvePattern(schema: TSchema): string { - const keys = ResolveKeys(schema, { includePatterns: true }) + export function Pattern(schema: TSchema): string { + const keys = Keys(schema, { includePatterns: true }) const pattern = keys.map((key) => `(${UnwrapPattern(key)})`) return `^(${pattern.join('|')})$` } + /** Resolves an array of keys derived from this schema */ + export function Keys(schema: TSchema, options: IndexerOptions): string[] { + return [...new Set(Visit(schema, options))] + } +} +// -------------------------------------------------------------------------- +// Accessor +// -------------------------------------------------------------------------- +// prettier-ignore +export namespace Accessor { + function OptionalUnwrap(schema: TSchema[]): TSchema[] { + return schema.map((schema) => { + const { [Optional]: _, ...clone } = TypeClone.Type(schema) + return clone + }) + } + function IsIntersectOptional(schema: TSchema[]): boolean { + return schema.every((schema) => TypeGuard.TOptional(schema)) + } + function IsUnionOptional(schema: TSchema[]): boolean { + return schema.some((schema) => TypeGuard.TOptional(schema)) + } + function ResolveIntersect(schema: TIntersect): TSchema { + return IsIntersectOptional(schema.allOf) ? Type.Optional(Type.Intersect(OptionalUnwrap(schema.allOf))) : schema + } + function ResolveUnion(schema: TUnion): TSchema { + return IsUnionOptional(schema.anyOf) ? Type.Optional(Type.Union(OptionalUnwrap(schema.anyOf))) : schema + } + function ResolveOptional(schema: TSchema) { + switch(true) { + case schema[Kind] === 'Intersect': return ResolveIntersect(schema as TIntersect) + case schema[Kind] === 'Union': return ResolveUnion(schema as TUnion) + default: return schema + } + } + function TIntersect(schema: TIntersect, key: string): TSchema { + const resolved = schema.allOf.reduce((acc, schema) => { + const indexed = Visit(schema, key) + return indexed[Kind] === 'Never' ? acc : [...acc, indexed] + }, [] as TSchema[]) + return ResolveOptional(Type.Intersect(resolved)) + } + function TUnion(schema: TUnion, key: string): TSchema { + const resolved = schema.anyOf.map((schema) => Visit(schema, key)) + return ResolveOptional(Type.Union(resolved)) + } + function TObject(schema: TObject, key: string): TSchema { + const property = schema.properties[key] + return ValueGuard.IsUndefined(property) ? Type.Never() : Type.Union([property]) + } + function TTuple(schema: TTuple, key: string): TSchema { + const items = schema.items + if (ValueGuard.IsUndefined(items)) return Type.Never() + const element = items[key as any as number] // + if (ValueGuard.IsUndefined(element)) return Type.Never() + return element + } + function Visit(schema: TSchema, key: string): TSchema { + switch(true) { + case schema[Kind] === 'Intersect': return TIntersect(schema as TIntersect, key) + case schema[Kind] === 'Union': return TUnion(schema as TUnion, key) + case schema[Kind] === 'Object': return TObject(schema as TObject, key) + case schema[Kind] === 'Tuple': return TTuple(schema as TTuple, key) + default: return Type.Never() + } + } + export function Resolve(schema: TSchema, keys: TPropertyKey[], options: SchemaOptions = {}): TSchema { + const resolved = keys.map((key) => Visit(schema, key.toString())) + return ResolveOptional(Type.Union(resolved, options)) + } } // -------------------------------------------------------------------------- // KeyArrayResolver // -------------------------------------------------------------------------- export class KeyArrayResolverError extends TypeBoxError {} +// prettier-ignore export namespace KeyArrayResolver { /** Resolves an array of string[] keys from the given schema or array type. */ export function Resolve(schema: TSchema | string[]): string[] { // prettier-ignore return Array.isArray(schema) ? schema : TypeGuard.TUnionLiteral(schema) ? schema.anyOf.map((schema) => schema.const.toString()) : - TypeGuard.TLiteral(schema) ? [schema.const as string] : - TypeGuard.TTemplateLiteral(schema) ? (() => { - const expression = TemplateLiteralParser.ParseExact(schema.pattern) - if (!TemplateLiteralFinite.Check(expression)) throw new KeyArrayResolverError('Cannot resolve keys from infinite template expression') - return [...TemplateLiteralGenerator.Generate(expression)] - })() : [] + TypeGuard.TLiteral(schema) ? [schema.const as string] : + TypeGuard.TTemplateLiteral(schema) ? (() => { + const expression = TemplateLiteralParser.ParseExact(schema.pattern) + if (!TemplateLiteralFinite.Check(expression)) throw new KeyArrayResolverError('Cannot resolve keys from infinite template expression') + return [...TemplateLiteralGenerator.Generate(expression)] + })() : [] } } // -------------------------------------------------------------------------- @@ -2687,14 +2666,14 @@ export namespace TemplateLiteralPattern { // prettier-ignore return ( TypeGuard.TTemplateLiteral(schema) ? schema.pattern.slice(1, schema.pattern.length - 1) : - TypeGuard.TUnion(schema) ? `(${schema.anyOf.map((schema) => Visit(schema, acc)).join('|')})` : - TypeGuard.TNumber(schema) ? `${acc}${PatternNumber}` : - TypeGuard.TInteger(schema) ? `${acc}${PatternNumber}` : - TypeGuard.TBigInt(schema) ? `${acc}${PatternNumber}` : - TypeGuard.TString(schema) ? `${acc}${PatternString}` : - TypeGuard.TLiteral(schema) ? `${acc}${Escape(schema.const.toString())}` : - TypeGuard.TBoolean(schema) ? `${acc}${PatternBoolean}` : - Throw(`Unexpected Kind '${schema[Kind]}'`) + TypeGuard.TUnion(schema) ? `(${schema.anyOf.map((schema) => Visit(schema, acc)).join('|')})` : + TypeGuard.TNumber(schema) ? `${acc}${PatternNumber}` : + TypeGuard.TInteger(schema) ? `${acc}${PatternNumber}` : + TypeGuard.TBigInt(schema) ? `${acc}${PatternNumber}` : + TypeGuard.TString(schema) ? `${acc}${PatternString}` : + TypeGuard.TLiteral(schema) ? `${acc}${Escape(schema.const.toString())}` : + TypeGuard.TBoolean(schema) ? `${acc}${PatternBoolean}` : + Throw(`Unexpected Kind '${schema[Kind]}'`) ) } export function Create(kinds: TTemplateLiteralKind[]): string { @@ -2814,15 +2793,15 @@ export namespace TemplateLiteralParser { // prettier-ignore return (expressions.length === 0) ? { type: 'const', const: '' } : (expressions.length === 1) ? expressions[0] : - { type: 'and', expr: expressions } + { type: 'and', expr: expressions } } /** Parses a pattern and returns an expression tree */ export function Parse(pattern: string): Expression { // prettier-ignore return IsGroup(pattern) ? Parse(InGroup(pattern)) : IsPrecedenceOr(pattern) ? Or(pattern) : - IsPrecedenceAnd(pattern) ? And(pattern) : - { type: 'const', const: pattern } + IsPrecedenceAnd(pattern) ? And(pattern) : + { type: 'const', const: pattern } } /** Parses a pattern and strips forward and trailing ^ and $ */ export function ParseExact(pattern: string): Expression { @@ -2840,22 +2819,22 @@ export namespace TemplateLiteralFinite { function IsNumber(expression: TemplateLiteralParser.Expression): boolean { // prettier-ignore return ( - expression.type === 'or' && - expression.expr.length === 2 && - expression.expr[0].type === 'const' && - expression.expr[0].const === '0' && - expression.expr[1].type === 'const' && + expression.type === 'or' && + expression.expr.length === 2 && + expression.expr[0].type === 'const' && + expression.expr[0].const === '0' && + expression.expr[1].type === 'const' && expression.expr[1].const === '[1-9][0-9]*' ) } function IsBoolean(expression: TemplateLiteralParser.Expression): boolean { // prettier-ignore return ( - expression.type === 'or' && - expression.expr.length === 2 && - expression.expr[0].type === 'const' && - expression.expr[0].const === 'true' && - expression.expr[1].type === 'const' && + expression.type === 'or' && + expression.expr.length === 2 && + expression.expr[0].type === 'const' && + expression.expr[0].const === 'true' && + expression.expr[1].type === 'const' && expression.expr[1].const === 'false' ) } @@ -2866,10 +2845,10 @@ export namespace TemplateLiteralFinite { // prettier-ignore return IsBoolean(expression) ? true : IsNumber(expression) || IsString(expression) ? false : - (expression.type === 'and') ? expression.expr.every((expr) => Check(expr)) : - (expression.type === 'or') ? expression.expr.every((expr) => Check(expr)) : - (expression.type === 'const') ? true : - Throw(`Unknown expression type`) + (expression.type === 'and') ? expression.expr.every((expr) => Check(expr)) : + (expression.type === 'or') ? expression.expr.every((expr) => Check(expr)) : + (expression.type === 'const') ? true : + Throw(`Unknown expression type`) } } // -------------------------------------------------------------------------------------- @@ -2898,9 +2877,9 @@ export namespace TemplateLiteralGenerator { // prettier-ignore return ( expression.type === 'and' ? yield* And(expression) : - expression.type === 'or' ? yield* Or(expression) : - expression.type === 'const' ? yield* Const(expression) : - (() => { throw new TemplateLiteralGeneratorError('Unknown expression') })() + expression.type === 'or' ? yield* Or(expression) : + expression.type === 'const' ? yield* Const(expression) : + (() => { throw new TemplateLiteralGeneratorError('Unknown expression') })() ) } } @@ -2913,17 +2892,17 @@ export namespace TemplateLiteralDslParser { // prettier-ignore return ( trim === 'boolean' ? yield Type.Boolean() : - trim === 'number' ? yield Type.Number() : - trim === 'bigint' ? yield Type.BigInt() : - trim === 'string' ? yield Type.String() : - yield (() => { - const literals = trim.split('|').map((literal) => Type.Literal(literal.trim())) - return ( - literals.length === 0 ? Type.Never() : - literals.length === 1 ? literals[0] : - Type.Union(literals) - ) - })() + trim === 'number' ? yield Type.Number() : + trim === 'bigint' ? yield Type.BigInt() : + trim === 'string' ? yield Type.String() : + yield (() => { + const literals = trim.split('|').map((literal) => Type.Literal(literal.trim())) + return ( + literals.length === 0 ? Type.Never() : + literals.length === 1 ? literals[0] : + Type.Union(literals) + ) + })() ) } function* ParseTerminal(template: string): IterableIterator { @@ -3052,7 +3031,7 @@ export class JsonTypeBuilder extends TypeBuilder { /** `[Json]` Creates a Composite object type */ public Composite(objects: [...T], options?: ObjectOptions): TComposite { const intersect: any = Type.Intersect(objects, {}) - const keys = KeyResolver.ResolveKeys(intersect, { includePatterns: false }) + const keys = Indexer.Keys(intersect, { includePatterns: false }) const properties = keys.reduce((acc, key) => ({ ...acc, [key]: Type.Index(intersect, [key]) }), {} as TProperties) return Type.Object(properties, options) as TComposite } @@ -3081,13 +3060,13 @@ export class JsonTypeBuilder extends TypeBuilder { // prettier-ignore return ( TypeGuard.TTemplateLiteral(unionType) ? this.Exclude(TemplateLiteralResolver.Resolve(unionType), excludedMembers, options) : - TypeGuard.TTemplateLiteral(excludedMembers) ? this.Exclude(unionType, TemplateLiteralResolver.Resolve(excludedMembers), options) : - TypeGuard.TUnion(unionType) ? (() => { - const narrowed = unionType.anyOf.filter((inner) => TypeExtends.Extends(inner, excludedMembers) === TypeExtendsResult.False) - return (narrowed.length === 1 ? TypeClone.Type(narrowed[0], options) : this.Union(narrowed, options)) as TExclude - })() : - TypeExtends.Extends(unionType, excludedMembers) !== TypeExtendsResult.False ? this.Never(options) : - TypeClone.Type(unionType, options) + TypeGuard.TTemplateLiteral(excludedMembers) ? this.Exclude(unionType, TemplateLiteralResolver.Resolve(excludedMembers), options) : + TypeGuard.TUnion(unionType) ? (() => { + const narrowed = unionType.anyOf.filter((inner) => TypeExtends.Extends(inner, excludedMembers) === TypeExtendsResult.False) + return (narrowed.length === 1 ? TypeClone.Type(narrowed[0], options) : this.Union(narrowed, options)) as TExclude + })() : + TypeExtends.Extends(unionType, excludedMembers) !== TypeExtendsResult.False ? this.Never(options) : + TypeClone.Type(unionType, options) ) as TExclude } /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ @@ -3095,13 +3074,13 @@ export class JsonTypeBuilder extends TypeBuilder { // prettier-ignore return ( TypeGuard.TTemplateLiteral(type) ? this.Extract(TemplateLiteralResolver.Resolve(type), union, options) : - TypeGuard.TTemplateLiteral(union) ? this.Extract(type, TemplateLiteralResolver.Resolve(union) as any, options) : - TypeGuard.TUnion(type) ? (() => { - const narrowed = type.anyOf.filter((inner) => TypeExtends.Extends(inner, union) !== TypeExtendsResult.False) - return (narrowed.length === 1 ? TypeClone.Type(narrowed[0], options) : this.Union(narrowed, options)) - })() : - TypeExtends.Extends(type, union) !== TypeExtendsResult.False ? TypeClone.Type(type, options) : - this.Never(options) + TypeGuard.TTemplateLiteral(union) ? this.Extract(type, TemplateLiteralResolver.Resolve(union) as any, options) : + TypeGuard.TUnion(type) ? (() => { + const narrowed = type.anyOf.filter((inner) => TypeExtends.Extends(inner, union) !== TypeExtendsResult.False) + return (narrowed.length === 1 ? TypeClone.Type(narrowed[0], options) : this.Union(narrowed, options)) + })() : + TypeExtends.Extends(type, union) !== TypeExtendsResult.False ? TypeClone.Type(type, options) : + this.Never(options) ) as TExtract } // /** `[Json]` Returns an Indexed property type for the given keys */ @@ -3122,7 +3101,7 @@ export class JsonTypeBuilder extends TypeBuilder { // public Index(schema: T, key: K, options?: SchemaOptions): TSchema /** `[Json]` Returns an Indexed property type for the given keys */ - public Index>(schema: T, keys: I, options?: SchemaOptions): TIndex + public Index>(schema: T, keys: I, options?: SchemaOptions): TIndex /** `[Json]` Returns an Indexed property type for the given keys */ public Index(schema: T, keys: [...K], options?: SchemaOptions): TIndex /** `[Json]` Returns an Indexed property type for the given keys */ @@ -3131,16 +3110,16 @@ export class JsonTypeBuilder extends TypeBuilder { return ( TypeGuard.TArray(schema) && TypeGuard.TNumber(unresolved) ? (() => { return TypeClone.Type(schema.items, options) - })() : - TypeGuard.TTuple(schema) && TypeGuard.TNumber(unresolved) ? (() => { - const items = ValueGuard.IsUndefined(schema.items) ? [] : schema.items - const cloned = items.map((schema) => TypeClone.Type(schema)) - return this.Union(cloned, options) - })() : (() => { - const keys = KeyArrayResolver.Resolve(unresolved) - const clone = TypeClone.Type(schema) - return IndexedAccessor.Resolve(clone, keys, options) - })() + })() : + TypeGuard.TTuple(schema) && TypeGuard.TNumber(unresolved) ? (() => { + const items = ValueGuard.IsUndefined(schema.items) ? [] : schema.items + const cloned = items.map((schema) => TypeClone.Type(schema)) + return this.Union(cloned, options) + })() : (() => { + const keys = KeyArrayResolver.Resolve(unresolved) + const clone = TypeClone.Type(schema) + return Accessor.Resolve(clone, keys, options) + })() ) } /** `[Json]` Creates an Integer type */ @@ -3161,8 +3140,8 @@ export class JsonTypeBuilder extends TypeBuilder { const objects = allOf.every((schema) => TypeGuard.TObject(schema)) const cloned = TypeClone.Rest(allOf) // prettier-ignore - const clonedUnevaluatedProperties = TypeGuard.TSchema(options.unevaluatedProperties) - ? { unevaluatedProperties: TypeClone.Type(options.unevaluatedProperties) } + const clonedUnevaluatedProperties = TypeGuard.TSchema(options.unevaluatedProperties) + ? { unevaluatedProperties: TypeClone.Type(options.unevaluatedProperties) } : {} return options.unevaluatedProperties === false || TypeGuard.TSchema(options.unevaluatedProperties) || objects ? this.Create({ ...options, ...clonedUnevaluatedProperties, [Kind]: 'Intersect', type: 'object', allOf: cloned }) @@ -3176,23 +3155,23 @@ export class JsonTypeBuilder extends TypeBuilder { const pattern = Object.getOwnPropertyNames(schema.patternProperties)[0] return ( pattern === PatternNumberExact ? this.Number(options) : - pattern === PatternStringExact ? this.String(options) : - this.Throw('Unable to resolve key type from Record key pattern') + pattern === PatternStringExact ? this.String(options) : + this.Throw('Unable to resolve key type from Record key pattern') ) })() : - TypeGuard.TTuple(schema) ? (() => { - const items = ValueGuard.IsUndefined(schema.items) ? [] : schema.items - const literals = items.map((_, index) => Type.Literal(index.toString())) - return this.Union(literals, options) - })() : - TypeGuard.TArray(schema) ? (() => { - return this.Number(options) - })() : (() => { - const keys = KeyResolver.ResolveKeys(schema, { includePatterns: false }) - if (keys.length === 0) return this.Never(options) as TKeyOf - const literals = keys.map((key) => this.Literal(key)) - return this.Union(literals, options) - })() + TypeGuard.TTuple(schema) ? (() => { + const items = ValueGuard.IsUndefined(schema.items) ? [] : schema.items + const literals = items.map((_, index) => Type.Literal(index.toString())) + return this.Union(literals, options) + })() : + TypeGuard.TArray(schema) ? (() => { + return this.Number(options) + })() : (() => { + const keys = Indexer.Keys(schema, { includePatterns: false }) + if (keys.length === 0) return this.Never(options) as TKeyOf + const literals = keys.map((key) => this.Literal(key)) + return this.Union(literals, options) + })() ) as unknown as TKeyOf } /** `[Json]` Creates a Literal type */ @@ -3299,29 +3278,29 @@ export class JsonTypeBuilder extends TypeBuilder { // prettier-ignore return TemplateLiteralFinite.Check(expression) ? (this.Object([...TemplateLiteralGenerator.Generate(expression)].reduce((acc, key) => ({ ...acc, [key]: TypeClone.Type(schema) }), {} as TProperties), options)) - : this.Create({ ...options, [Kind]: 'Record', type: 'object', patternProperties: { [key.pattern]: TypeClone.Type(schema) }}) + : this.Create({ ...options, [Kind]: 'Record', type: 'object', patternProperties: { [key.pattern]: TypeClone.Type(schema) } }) })() : - TypeGuard.TUnion(key) ? (() => { - const union = UnionResolver.Resolve(key) - if (TypeGuard.TUnionLiteral(union)) { - const properties = union.anyOf.reduce((acc: any, literal: any) => ({ ...acc, [literal.const]: TypeClone.Type(schema) }), {} as TProperties) - return this.Object(properties, { ...options, [Hint]: 'Record' }) - } else this.Throw('Record key of type union contains non-literal types') - })() : - TypeGuard.TLiteral(key) ? (() => { - // prettier-ignore - return (ValueGuard.IsString(key.const) || ValueGuard.IsNumber(key.const)) - ? this.Object({ [key.const]: TypeClone.Type(schema) }, options) - : this.Throw('Record key of type literal is not of type string or number') - })() : - TypeGuard.TInteger(key) || TypeGuard.TNumber(key) ? (() => { - return this.Create({ ...options, [Kind]: 'Record', type: 'object', patternProperties: { [PatternNumberExact]: TypeClone.Type(schema) } }) - })() : - TypeGuard.TString(key) ? (() => { - const pattern = ValueGuard.IsUndefined(key.pattern) ? PatternStringExact : key.pattern - return this.Create({ ...options, [Kind]: 'Record', type: 'object', patternProperties: { [pattern]: TypeClone.Type(schema) } }) - })() : - this.Never() + TypeGuard.TUnion(key) ? (() => { + const union = UnionResolver.Resolve(key) + if (TypeGuard.TUnionLiteral(union)) { + const properties = union.anyOf.reduce((acc: any, literal: any) => ({ ...acc, [literal.const]: TypeClone.Type(schema) }), {} as TProperties) + return this.Object(properties, { ...options, [Hint]: 'Record' }) + } else this.Throw('Record key of type union contains non-literal types') + })() : + TypeGuard.TLiteral(key) ? (() => { + // prettier-ignore + return (ValueGuard.IsString(key.const) || ValueGuard.IsNumber(key.const)) + ? this.Object({ [key.const]: TypeClone.Type(schema) }, options) + : this.Throw('Record key of type literal is not of type string or number') + })() : + TypeGuard.TInteger(key) || TypeGuard.TNumber(key) ? (() => { + return this.Create({ ...options, [Kind]: 'Record', type: 'object', patternProperties: { [PatternNumberExact]: TypeClone.Type(schema) } }) + })() : + TypeGuard.TString(key) ? (() => { + const pattern = ValueGuard.IsUndefined(key.pattern) ? PatternStringExact : key.pattern + return this.Create({ ...options, [Kind]: 'Record', type: 'object', patternProperties: { [pattern]: TypeClone.Type(schema) } }) + })() : + this.Never() ) } /** `[Json]` Creates a Recursive type */ @@ -3382,8 +3361,8 @@ export class JsonTypeBuilder extends TypeBuilder { const [additionalItems, minItems, maxItems] = [false, items.length, items.length] const clonedItems = TypeClone.Rest(items) // prettier-ignore - const schema = (items.length > 0 ? - { ...options, [Kind]: 'Tuple', type: 'array', items: clonedItems, additionalItems, minItems, maxItems } : + const schema = (items.length > 0 ? + { ...options, [Kind]: 'Tuple', type: 'array', items: clonedItems, additionalItems, minItems, maxItems } : { ...options, [Kind]: 'Tuple', type: 'array', minItems, maxItems }) as any return this.Create(schema) } @@ -3402,7 +3381,7 @@ export class JsonTypeBuilder extends TypeBuilder { /** `[Json]` Creates a Union type */ public Union(union: TSchema[] | TTemplateLiteral, options: SchemaOptions = {}) { // prettier-ignore - return TypeGuard.TTemplateLiteral(union) + return TypeGuard.TTemplateLiteral(union) ? TemplateLiteralResolver.Resolve(union) : (() => { const anyOf = union @@ -3442,10 +3421,10 @@ export class JavaScriptTypeBuilder extends JsonTypeBuilder { })() : rest // prettier-ignore return ( - TypeGuard.TIntersect(schema) ? Type.Intersect(Unwrap(schema.allOf)) : - TypeGuard.TUnion(schema) ? Type.Union(Unwrap(schema.anyOf)) : - TypeGuard.TPromise(schema) ? this.Awaited(schema.item) : - TypeClone.Type(schema, options) + TypeGuard.TIntersect(schema) ? Type.Intersect(Unwrap(schema.allOf)) : + TypeGuard.TUnion(schema) ? Type.Union(Unwrap(schema.anyOf)) : + TypeGuard.TPromise(schema) ? this.Awaited(schema.item) : + TypeClone.Type(schema, options) ) as TAwaited } /** `[JavaScript]` Creates a BigInt type */ diff --git a/src/value/check.ts b/src/value/check.ts index 7e987708c..33dde03a7 100644 --- a/src/value/check.ts +++ b/src/value/check.ts @@ -164,11 +164,11 @@ function TInteger(schema: Types.TInteger, references: Types.TSchema[], value: an function TIntersect(schema: Types.TIntersect, references: Types.TSchema[], value: any): boolean { const check1 = schema.allOf.every((schema) => Visit(schema, references, value)) if (schema.unevaluatedProperties === false) { - const keyPattern = new RegExp(Types.KeyResolver.ResolvePattern(schema)) + const keyPattern = new RegExp(Types.Indexer.Pattern(schema)) const check2 = Object.getOwnPropertyNames(value).every((key) => keyPattern.test(key)) return check1 && check2 } else if (Types.TypeGuard.TSchema(schema.unevaluatedProperties)) { - const keyCheck = new RegExp(Types.KeyResolver.ResolvePattern(schema)) + const keyCheck = new RegExp(Types.Indexer.Pattern(schema)) const check2 = Object.getOwnPropertyNames(value).every((key) => keyCheck.test(key) || Visit(schema.unevaluatedProperties as Types.TSchema, references, value[key])) return check1 && check2 } else { diff --git a/src/value/transform.ts b/src/value/transform.ts index bb377f9a1..9f69ad942 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.ResolveKeys(schema, { includePatterns: false }) + const knownKeys = Types.Indexer.Keys(schema, { includePatterns: false }) const knownProperties = knownKeys.reduce((value, key) => { return (key in value) - ? { ...value, [key]: Visit(Types.IndexedAccessor.Resolve(schema, [key]), references, value[key]) } + ? { ...value, [key]: Visit(Types.Accessor.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.ResolveKeys(schema, { includePatterns: false }) + const knownKeys = Types.Indexer.Keys(schema, { includePatterns: false }) 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.ResolveKeys(schema, { includePatterns: false }) + const knownKeys = Types.Indexer.Keys(schema, { includePatterns: false }) const knownProperties = knownKeys.reduce((value, key) => { return key in defaulted - ? { ...value, [key]: Visit(Types.IndexedAccessor.Resolve(schema, [key]), references, value[key]) } + ? { ...value, [key]: Visit(Types.Accessor.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.ResolveKeys(schema, { includePatterns: false }) + const knownKeys = Types.Indexer.Keys(schema, { includePatterns: false }) const knownProperties = knownKeys.reduce((value, key) => { return key in value ? { ...value, [key]: Visit(schema.properties[key], references, value[key]) } diff --git a/test/static/indexed.ts b/test/static/indexed.ts index 31580c194..210e63fe1 100644 --- a/test/static/indexed.ts +++ b/test/static/indexed.ts @@ -54,13 +54,13 @@ import { Type, Static } from '@sinclair/typebox' const A = Type.Object({}) const R = Type.Index(A, Type.BigInt()) // Support Overload type O = Static - Expect(R).ToStatic() + Expect(R).ToStaticNever() } { const A = Type.Array(Type.Number()) const R = Type.Index(A, Type.BigInt()) // Support Overload type O = Static - Expect(R).ToStatic() + Expect(R).ToStaticNever() } // ------------------------------------------------------------------ // Intersections