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 22, 2023
1 parent bd6e8a4 commit da152e6
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 138 deletions.
233 changes: 96 additions & 137 deletions examples/index.ts
Original file line number Diff line number Diff line change
@@ -1,184 +1,143 @@
import { TypeSystem } from '@sinclair/typebox/system'
import { TypeCompiler } from '@sinclair/typebox/compiler'
import { Value, ValuePointer } from '@sinclair/typebox/value'
import { Type, TypeGuard, Kind, Static, TSchema, TProperties, TArray, TLiteral, TTemplateLiteral } from '@sinclair/typebox'
import { TObject, TUnion, TInteger, TBigInt, TIntersect, TString, TNumber, TBoolean, TNever, TTuple, UnionType, TRecursive } from '@sinclair/typebox'

export type EmptyString = ''

export type Filter<T extends TSchema[], U extends TSchema> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? L extends U ? [L, ...Filter<R, U>] : Filter<R, U>
: []
// ------------------------------------------------------------------
// TemplateLiteralFinite
// ------------------------------------------------------------------
// prettier-ignore
export type IsTemplateLiteralFiniteCheck<T> =
T extends TTemplateLiteral<infer S> ? IsTemplateLiteralFiniteRest<S> :
T extends TUnion<infer S> ? IsTemplateLiteralFiniteRest<S> :
T extends TString ? false :
T extends TBoolean ? false :
T extends TNumber ? false :
T extends TInteger ? false :
T extends TBigInt ? false :
T extends TLiteral ? true :
false
// prettier-ignore
export type IsTemplateLiteralFiniteRest<T extends TTemplateLiteralKind[]> =
T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]]
? IsTemplateLiteralFiniteCheck<L> extends false
? false
: IsTemplateLiteralFiniteRest<R>
: true
// prettier-ignore
export type IsTemplateLiteralFinite<T extends TTemplateLiteralKind> =
T extends TTemplateLiteral<infer U>
? IsTemplateLiteralFiniteRest<U>
: false
// ------------------------------------------------------------------
// TemplateLiteralRest
// ------------------------------------------------------------------
// prettier-ignore
export type TTemplateLiteralKind =
| TUnion
| TLiteral
| TInteger
| TTemplateLiteral
| TNumber
| TBigInt
| TString
| TBoolean
| TNever

// prettier-ignore
export type TTemplateLiteralUnion<T extends TSchema[]> =
T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]]
? `${TTemplateLiteralString<L>}` | `${TTemplateLiteralUnion<R>}`
: ''
// prettier-ignore
export type TTemplateLiteralString<T extends TTemplateLiteralKind> =
T extends TTemplateLiteral<infer S> ? `${TTemplateLiteralRest<S>}` :
T extends TUnion<infer S> ? TTemplateLiteralUnion<S> :
T extends TLiteral<infer S> ? `${S}` :
T extends TString ? `${string}` :
T extends TInteger ? `${number}` :
T extends TNumber ? `${number}` :
T extends TBigInt ? `${bigint}` :
T extends TBoolean ? `${boolean}` :
''
// prettier-ignore
export type TTemplateLiteralRest<T extends TSchema[]> =
T extends [infer L extends TTemplateLiteralKind, ...infer R extends TTemplateLiteralKind[]]
? `${TTemplateLiteralString<L>}${TTemplateLiteralRest<R>}`
: ''

const T = Type.TemplateLiteral('a${1|2|3}z')

type Map<T> = T extends TTemplateLiteral<infer S> ? TTemplateLiteralRest<S> : ''

type Q = Map<typeof T>

type H = Static<typeof T>

type X = ['A', 'B', 'C']

// ------------------------------------------------------------------
// TIndexer
// ------------------------------------------------------------------
// prettier-ignore
export type TIndexerUnion<T extends TSchema[]> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? [...TIndexer<L>, ...TIndexerUnion<R>]
: []
// prettier-ignore
export type TIndexer<T extends TSchema> =
T extends TTemplateLiteral<infer S> ? TTemplateLiteralRest<S> :
T extends TUnion<infer S> ? TIndexerUnion<S> :
T extends TLiteral<infer S> ? [S] :
T extends TString ? [string] :
T extends TNumber ? [number] :
[]
import { Type, Static, TSchema, TProperties, TArray, TLiteral, TTemplateLiteral, TypeGuard, TemplateLiteralParser, TemplateLiteralGenerator, TemplateLiteralResolver } from '@sinclair/typebox'
import { TObject, TUnion, UnionToTuple, TInteger, TBigInt, TIntersect, TString, TNumber, TBoolean, TNever, TTuple, UnionType, TRecursive } from '@sinclair/typebox'

// ------------------------------------------------------------------
// TIndex
// ------------------------------------------------------------------
// prettier-ignore
export type TIndexProperties<T extends TProperties, K extends PropertyKey> =
K extends keyof T
? [T[K]]
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]]
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 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>]
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>]
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>
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>]
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>
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> =
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 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 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[] = TIndexer<I>>(schema: T, keys: I): TIndex<T, K>
export function Index<T extends TSchema, I extends TSchema, K extends PropertyKey[] = TIndexer<I>>(schema: T, keys: I): TIndex<T, K>
export function Index(schema: TSchema, keys: unknown): any {

}
// ------------------------------------------------------------------
// TIndexer
// ------------------------------------------------------------------
export type TIndexerTemplateLiteral<T extends TTemplateLiteral> = UnionToTuple<Static<T>>
export type TIndexerUnion<T extends TSchema[]> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? [...TIndexer<L>, ...TIndexerUnion<R>]
: []
// prettier-ignore
export type TIndexer<T extends TSchema> =
T extends TTemplateLiteral ? TIndexerTemplateLiteral<T> :
T extends TUnion<infer S> ? TIndexerUnion<S> :
T extends TLiteral<infer S> ? [S] :
T extends TString ? [string] :
T extends TNumber ? [number] :
T extends TInteger ? [number] :
T extends TBigInt ? [bigint] :
[]

export namespace Indexer {
function TIndexerTemplateLiteral(schema: TUnion<TLiteral[]> | TString | TNever): string[] {
switch(true) {
case TypeGuard.TUnionLiteral(schema): return schema.anyOf.map(schema => schema.const.toString())
case TypeGuard.TString(schema): return [`{string}`]
default: return []
}
}
function TIndexerUnion(schemas: TSchema[]): string[] {
const [L, R] = [schemas.slice(0, 1), ...schemas.slice(1)]
return []
}
function Visit(schema: TSchema, keys: string): string[] {
switch (true) {
case TypeGuard.TTemplateLiteral(schema): return TIndexerTemplateLiteral(TemplateLiteralResolver.Resolve(schema))
case TypeGuard.TUnion(schema): return TIndexerUnion(schema.anyOf)
case TypeGuard.TLiteral(schema): return [schema.const.toString()]
case TypeGuard.TString(schema): return ['{string}']
case TypeGuard.TNumber(schema): return ['{number}']
case TypeGuard.TInteger(schema): return ['{number}']
case TypeGuard.TBigInt(schema): return ['{bigint}']
default: return []
}
}
}




const A = Type.TemplateLiteral('a${1|2|3}')

const R = TemplateLiteralResolver.Resolve(A)
console.log(R)

const S = Type.Intersect([
Type.Object({ x: Type.Number() }),
Type.Object({ y: Type.String() })
Type.Object({ y: Type.String() }),
Type.Object({ z: Type.Boolean() })
])

const A = Type.TemplateLiteral('${x|y}')

type A = TIndexer<typeof A>

const I = Index(S, Type.TemplateLiteral('${x|y}'))
// const T = Type.Object({
// x: Type.Object({
// y: Type.Object({
// i: Index(S, Type.TemplateLiteral('${x|a}'))
// })
// })
// })

type S = Array<string>
// type T = Static<typeof T>


// type A = TObject<{ x: TNumber }>
Expand Down
2 changes: 1 addition & 1 deletion src/typebox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2593,7 +2593,7 @@ export namespace TemplateLiteralPattern {
// --------------------------------------------------------------------------------------
export namespace TemplateLiteralResolver {
/** Resolves a template literal as a TUnion */
export function Resolve(template: TTemplateLiteral): TString | TUnion | TLiteral {
export function Resolve(template: TTemplateLiteral): TNever | TString | TUnion<TLiteral[]> {
const expression = TemplateLiteralParser.ParseExact(template.pattern)
if (!TemplateLiteralFinite.Check(expression)) return Type.String()
const literals = [...TemplateLiteralGenerator.Generate(expression)].map((value) => Type.Literal(value))
Expand Down

0 comments on commit da152e6

Please sign in to comment.