From cdf454e747132153014856b4163bc7e7b9d3d362 Mon Sep 17 00:00:00 2001 From: sinclair Date: Thu, 23 Nov 2023 14:35:05 +0900 Subject: [PATCH] Reimplement Index Types --- examples/index.ts | 256 +++++++++++++---------------------------- src/typebox.ts | 34 ++---- test/static/indexed.ts | 3 + 3 files changed, 97 insertions(+), 196 deletions(-) diff --git a/examples/index.ts b/examples/index.ts index 8c7fdac6a..dbf625510 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -1,182 +1,92 @@ 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, - TemplateLiteralGenerator, - TemplateLiteralResolver, - TemplateLiteralFinite, - IsTemplateLiteralFiniteCheck, - KeyResolver, - TOptional, - UnionTypeIsOptional, -} from '@sinclair/typebox' +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 { TObject } from '@sinclair/typebox' -const A = Type.Intersect([Type.String(), Type.String()]) -const I = Type.Composite([ - Type.Composite([Type.Object({ x: Type.String(), y: Type.Literal(1) }), Type.Object({ x: Type.String(), y: Type.Number() })]), - Type.Composite([Type.Object({ x: Type.Boolean(), y: Type.Number() }), Type.Object({ x: Type.String() })]), -]) -const R = Type.Index(I, ['x']) +// ------------------------------------------------------------------ +// TIndex +// ------------------------------------------------------------------ // prettier-ignore -// export type UnionTypeIsOptional = -// T extends [infer L extends TSchema, ...infer R extends TSchema[]] -// ? L extends TOptional -// ? UnionTypeIsOptional -// : false -// : true - -type X = UnionTypeIsOptional<[ - TOptional, - TOptional, -]> - -// // ------------------------------------------------------------------ -// // TIndex -// // ------------------------------------------------------------------ -// // prettier-ignore -// export type TIndexProperties = -// K extends keyof T -// ? [T[K]] -// : [] -// // prettier-ignore -// export type TIndexTuple = -// K extends keyof T -// ? [T[K]] -// : [] -// // prettier-ignore -// export type TIndexArray = -// K extends number -// ? [T] -// : [] -// // prettier-ignore -// export type TIndexIntersect = -// T extends [infer L extends TSchema, ...infer R extends TSchema[]] -// ? [...TIndexKey, ...TIndexIntersect] -// : [] -// // prettier-ignore -// export type TIndexUnionGather = -// T extends [infer L extends TSchema, ...infer R extends TSchema[]] -// ? [TIndexKey, ...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 TIndexKey = -// T extends TRecursive ? TIndexKey : -// T extends TIntersect ? TIndexIntersect : -// T extends TUnion ? TIndexUnion : -// T extends TTuple ? TIndexTuple : -// T extends TArray ? TIndexArray : -// T extends TObject ? TIndexProperties : -// [] -// // prettier-ignore -// export type TIndexKeys = -// K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] -// ? [...TIndexKey, ...TIndexKeys] -// : [] -// export type TIndex> = UnionType - -// export function Index(schema: T, keys: [...K]): TIndex -// export function Index>(schema: T, keys: I): TIndex -// export function Index(schema: TSchema, keys: unknown): any { - -// } - -// import {} from '@sinclair/typebox' -// // ------------------------------------------------------------------ -// // TIndexer -// // ------------------------------------------------------------------ -// export type TKeyResolverTemplateLiteral> = -// F extends true -// ? UnionToTuple> -// : [] -// export type TKeyResolverUnion = -// T extends [infer L extends TSchema, ...infer R extends TSchema[]] -// ? [...TKeyResolver, ...TKeyResolverUnion] -// : [] -// // prettier-ignore -// export type TKeyResolver = -// T extends TTemplateLiteral ? TKeyResolverTemplateLiteral : -// T extends TUnion ? TKeyResolverUnion : -// T extends TLiteral ? [S] : -// T extends TString ? [] : -// T extends TNumber ? [] : -// T extends TInteger ? [] : -// T extends TBigInt ? [] : -// [] - -// const T = Type.TemplateLiteral('a${a|b}${string}') -// const S = KeyResolver.ResolveKeys(T, { includePatterns: false }) - -// console.log(S, 1) - -// console.log(S) - -// const E = Type.TemplateLiteral('a${string}') -// type E = TKeyResolver - -// const R = TemplateLiteralResolver.Resolve(A) -// console.log(R) - -// const S = Type.Intersect([ -// Type.Object({ x: Type.Number() }), -// Type.Object({ y: Type.String() }), -// Type.Object({ z: Type.Boolean() }) -// ]) - -// const T = Type.Object({ -// x: Type.Object({ -// y: Type.Object({ -// i: Index(S, Type.TemplateLiteral('${x|a}')) -// }) -// }) -// }) - -// type T = Static - -// type A = TObject<{ x: TNumber }> -// type B = TObject<{ x: TString }> -// type C = TIntersect<[A, B]> -// type X = TObject<{ x: TNumber }> -// type Y = TObject<{ y: TString }> -// type Z = TTuple<[X, Y]> - -// type T = TUnion<[C, Z]> - -// type S = TIndex - -// type Q = Array<{ x: 1 }> - -// type U = Q[number] - -export function Resolve(T: TObject<{}>, arg1: {}) { - throw new Error('Function not implemented.') -} +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 diff --git a/src/typebox.ts b/src/typebox.ts index be8309fb2..77c186f80 100644 --- a/src/typebox.ts +++ b/src/typebox.ts @@ -444,34 +444,22 @@ export type TKeyResolver = // ------------------------------------------------------------------ // TIndex // ------------------------------------------------------------------ -// prettier-ignore -export type TIndexProperties = - K extends keyof T - ? [T[K]] - : [] -// prettier-ignore -export type TIndexTuple = - K extends keyof T - ? [T[K]] - : [] -// prettier-ignore -export type TIndexArray = - K extends number - ? [T] - : [] +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] : [] // prettier-ignore export type TIndexIntersect = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? L extends TUnion - ? [TUnion>, ...TIndexIntersect] + ? L extends TIntersect + ? [IntersectType>, ...TIndexIntersect] + : L extends TUnion + ? [UnionType>, ...TIndexIntersect] : [...TIndexKeyResolve, ...TIndexIntersect] : [] // prettier-ignore export type TIndexUnionGather = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? L extends TIntersect - ? [TIntersect>, ...TIndexUnionGather] - : [TIndexKeyResolve, ...TIndexUnionGather] + ? [TIndexKeyResolve, ...TIndexUnionGather] : [] // prettier-ignore export type TIndexUnionCheck = @@ -502,7 +490,7 @@ export type TIndexKeyResolve = // prettier-ignore export type TIndexKey> = R extends TSchema[] - ? IntersectType + ? UnionType : TNever // prettier-ignore export type TIndexKeysResolve = @@ -511,8 +499,8 @@ export type TIndexKeysResolve = : [] // prettier-ignore export type TIndexKeys> = - R extends TSchema[] - ? UnionType + R extends TSchema[] + ? IntersectType : TNever export type TIndex = TIndexKeys // -------------------------------------------------------------------------- diff --git a/test/static/indexed.ts b/test/static/indexed.ts index 419ef477a..31580c194 100644 --- a/test/static/indexed.ts +++ b/test/static/indexed.ts @@ -174,6 +174,9 @@ import { Type, Static } from '@sinclair/typebox' const D = Type.Object({ x: Type.String() }) const I = Type.Intersect([Type.Intersect([A, B]), Type.Intersect([C, D])]) const R = Type.Index(I, ['x', 'y']) + + // TUnion<[TIntersect<[TIntersect<[TString, TNumber]>, TIntersect<[TString, TString]>]>, TIntersect<[TIntersect<[TLiteral<...>, TNumber]>, TNumber]>]> + // TUnion<[TUnion<[TString, TNumber, TString, TString]>, TUnion<[TLiteral<1>, TNumber, TNumber]>]> type O = Static Expect(R).ToStatic<1>() }