Skip to content

Commit

Permalink
Reimplement Index Types
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 committed Nov 23, 2023
1 parent 336a2ef commit cdf454e
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 196 deletions.
256 changes: 83 additions & 173 deletions examples/index.ts
Original file line number Diff line number Diff line change
@@ -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 TSchema[]> =
// T extends [infer L extends TSchema, ...infer R extends TSchema[]]
// ? L extends TOptional<L>
// ? UnionTypeIsOptional<R>
// : false
// : true

type X = UnionTypeIsOptional<[
TOptional<TNumber>,
TOptional<TNumber>,
]>

// // ------------------------------------------------------------------
// // TIndex
// // ------------------------------------------------------------------
// // prettier-ignore
// export type TIndexProperties<T extends TProperties, K extends PropertyKey> =
// K extends keyof T
// ? [T[K]]
// : []
// // prettier-ignore
// export type TIndexTuple<T extends TSchema[], K extends PropertyKey> =
// K extends keyof T
// ? [T[K]]
// : []
// // prettier-ignore
// export type TIndexArray<T extends TSchema, K extends PropertyKey> =
// K extends number
// ? [T]
// : []
// // prettier-ignore
// export type TIndexIntersect<T extends TSchema[], K extends PropertyKey> =
// T extends [infer L extends TSchema, ...infer R extends TSchema[]]
// ? [...TIndexKey<L, K>, ...TIndexIntersect<R, K>]
// : []
// // prettier-ignore
// export type TIndexUnionGather<T extends TSchema[], K extends PropertyKey> =
// T extends [infer L extends TSchema, ...infer R extends TSchema[]]
// ? [TIndexKey<L, K>, ...TIndexUnionGather<R, K>]
// : []
// // prettier-ignore
// export type TIndexUnionCheck<T extends TSchema[][]> =
// T extends [infer L extends TSchema[], ...infer R extends TSchema[][]]
// ? L extends []
// ? false
// : TIndexUnionCheck<R>
// : true
// // prettier-ignore
// export type TIndexUnionFinal<T extends TSchema[][]> =
// T extends [infer L extends TSchema[], ...infer R extends TSchema[][]]
// ? [...L, ...TIndexUnionFinal<R>]
// : []
// // prettier-ignore
// export type TIndexUnion<T extends TSchema[], K extends PropertyKey, G extends TSchema[][] = TIndexUnionGather<T, K>, C extends boolean = TIndexUnionCheck<G>> =
// C extends true
// ? TIndexUnionFinal<G>
// : []
// // prettier-ignore
// export type TIndexKey<T extends TSchema, K extends PropertyKey> =
// T extends TRecursive<infer S> ? TIndexKey<S, K> :
// T extends TIntersect<infer S> ? TIndexIntersect<S, K> :
// T extends TUnion<infer S> ? TIndexUnion<S, K> :
// T extends TTuple<infer S> ? TIndexTuple<S, K> :
// T extends TArray<infer S> ? TIndexArray<S, K> :
// T extends TObject<infer S> ? TIndexProperties<S, K> :
// []
// // prettier-ignore
// export type TIndexKeys<T extends TSchema, K extends PropertyKey[]> =
// K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]]
// ? [...TIndexKey<T, L>, ...TIndexKeys<T, R>]
// : []
// export type TIndex<T extends TSchema, K extends PropertyKey[], R extends TSchema[] = TIndexKeys<T, K>> = UnionType<R>

// export function Index<T extends TSchema, K extends string[]>(schema: T, keys: [...K]): TIndex<T, K>
// export function Index<T extends TSchema, I extends TSchema, K extends PropertyKey[] = TKeyResolver<I>>(schema: T, keys: I): TIndex<T, K>
// export function Index(schema: TSchema, keys: unknown): any {

// }

// import {} from '@sinclair/typebox'
// // ------------------------------------------------------------------
// // TIndexer
// // ------------------------------------------------------------------
// export type TKeyResolverTemplateLiteral<T extends TTemplateLiteral, F = IsTemplateLiteralFiniteCheck<T>> =
// F extends true
// ? UnionToTuple<Static<T>>
// : []
// export type TKeyResolverUnion<T extends TSchema[]> =
// T extends [infer L extends TSchema, ...infer R extends TSchema[]]
// ? [...TKeyResolver<L>, ...TKeyResolverUnion<R>]
// : []
// // prettier-ignore
// export type TKeyResolver<T extends TSchema> =
// T extends TTemplateLiteral ? TKeyResolverTemplateLiteral<T> :
// T extends TUnion<infer S> ? TKeyResolverUnion<S> :
// T extends TLiteral<infer S> ? [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<typeof E>

// 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<typeof T>

// 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<Z, [1]>

// 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 TSchema[]> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? L extends TNever
? [...TIndexDiscardNever<R>]
: [L, ...TIndexDiscardNever<R>]
: []
export type TIndexProperty<T extends TProperties, K extends PropertyKey> = K extends keyof T ? T[K] : TNever
export type TIndexTuple<T extends TSchema[], K extends PropertyKey> = K extends keyof T ? T[K] : TNever
export type TIndexArray<T extends TSchema, K extends PropertyKey> = K extends number ? T : TNever
// ------------------------------------------------------------------
// TIndex: Intersect
// ------------------------------------------------------------------
export type TIndexIntersect<T extends TSchema[], K extends PropertyKey> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? TIndexKey<L, K> extends infer N extends TSchema
? N extends TNever
? [...TIndexIntersect<R, K>]
: [N, ...TIndexIntersect<R, K>]
: []
: []
// ------------------------------------------------------------------
// TIndex: Union
// ------------------------------------------------------------------
// prettier-ignore
export type TIndexUnionCollect<T extends TSchema[], K extends PropertyKey> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? [TIndexKey<L, K>, ...TIndexUnionCollect<R, K>]
: []
// prettier-ignore
export type TIndexUnionCheck<T extends TSchema[][]> =
T extends [infer L extends TSchema[], ...infer R extends TSchema[][]]
? L extends []
? false
: TIndexUnionCheck<R>
: true
// prettier-ignore
export type TIndexUnion<
T extends TSchema[], K extends PropertyKey,
G extends TSchema[] = TIndexUnionCollect<T, K>,
C extends TSchema[] = TIndexDiscardNever<G>
> = C
// prettier-ignore
export type TIndexKey<T extends TSchema, K extends PropertyKey> =
T extends TRecursive<infer S> ? TIndexKey<S, K> :
T extends TIntersect<infer S> ? IntersectType<TIndexIntersect<S, K>> :
T extends TUnion<infer S> ? UnionType<TIndexUnion<S, K>> :
T extends TTuple<infer S> ? TIndexTuple<S, K> :
T extends TArray<infer S> ? TIndexArray<S, K> :
T extends TObject<infer S> ? TIndexProperty<S, K> :
TNever
// prettier-ignore
export type TIndexKeys<T extends TSchema, K extends PropertyKey[]> =
K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]]
? [TIndexKey<T, L>, ...TIndexKeys<T, R>]
: []

export type TIndex<T extends TSchema, K extends PropertyKey[]> = UnionType<TIndexKeys<T, K>>

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<I, ['y']>

type S = Static<C>
34 changes: 11 additions & 23 deletions src/typebox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,34 +444,22 @@ export type TKeyResolver<T extends TSchema> =
// ------------------------------------------------------------------
// TIndex
// ------------------------------------------------------------------
// prettier-ignore
export type TIndexProperties<T extends TProperties, K extends PropertyKey> =
K extends keyof T
? [T[K]]
: []
// prettier-ignore
export type TIndexTuple<T extends TSchema[], K extends PropertyKey> =
K extends keyof T
? [T[K]]
: []
// prettier-ignore
export type TIndexArray<T extends TSchema, K extends PropertyKey> =
K extends number
? [T]
: []
export type TIndexProperties<T extends TProperties, K extends PropertyKey> = K extends keyof T ? [T[K]] : []
export type TIndexTuple<T extends TSchema[], K extends PropertyKey> = K extends keyof T ? [T[K]] : []
export type TIndexArray<T extends TSchema, K extends PropertyKey> = K extends number ? [T] : []
// prettier-ignore
export type TIndexIntersect<T extends TSchema[], K extends PropertyKey> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? L extends TUnion<infer U>
? [TUnion<TIndexUnion<U, K>>, ...TIndexIntersect<R, K>]
? L extends TIntersect<infer S extends TSchema[]>
? [IntersectType<TIndexIntersect<S, K>>, ...TIndexIntersect<R, K>]
: L extends TUnion<infer S extends TSchema[]>
? [UnionType<TIndexUnion<S, K>>, ...TIndexIntersect<R, K>]
: [...TIndexKeyResolve<L, K>, ...TIndexIntersect<R, K>]
: []
// prettier-ignore
export type TIndexUnionGather<T extends TSchema[], K extends PropertyKey> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? L extends TIntersect<infer U>
? [TIntersect<TIndexIntersect<U, K>>, ...TIndexUnionGather<R, K>]
: [TIndexKeyResolve<L, K>, ...TIndexUnionGather<R, K>]
? [TIndexKeyResolve<L, K>, ...TIndexUnionGather<R, K>]
: []
// prettier-ignore
export type TIndexUnionCheck<T extends TSchema[][]> =
Expand Down Expand Up @@ -502,7 +490,7 @@ export type TIndexKeyResolve<T extends TSchema, K extends PropertyKey> =
// prettier-ignore
export type TIndexKey<T extends TSchema, K extends PropertyKey, R = TIndexKeyResolve<T, K>> =
R extends TSchema[]
? IntersectType<R>
? UnionType<R>
: TNever
// prettier-ignore
export type TIndexKeysResolve<T extends TSchema, K extends PropertyKey[]> =
Expand All @@ -511,8 +499,8 @@ export type TIndexKeysResolve<T extends TSchema, K extends PropertyKey[]> =
: []
// prettier-ignore
export type TIndexKeys<T extends TSchema, K extends PropertyKey[], R = TIndexKeysResolve<T, K>> =
R extends TSchema[]
? UnionType<R>
R extends TSchema[]
? IntersectType<R>
: TNever
export type TIndex<T extends TSchema, K extends PropertyKey[]> = TIndexKeys<T, K>
// --------------------------------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions test/static/indexed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof R>
Expect(R).ToStatic<1>()
}
Expand Down

0 comments on commit cdf454e

Please sign in to comment.