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 b76b135 commit 2b5fa1c
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 26 deletions.
143 changes: 134 additions & 9 deletions examples/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,141 @@
import { TypeSystem } from '@sinclair/typebox/system'
import { TypeCompiler } from '@sinclair/typebox/compiler'
import { Value, ValuePointer } from '@sinclair/typebox/value'
import { Type, Indexer, Accessor } from '@sinclair/typebox'
import { Type, Accessor, TemplateLiteralParser, TemplateLiteralFinite, TemplateLiteralResolver, TypeGuard, TIntersect, TUnion, TTemplateLiteral, IsTemplateLiteralFiniteCheck, UnionToTuple, Static, TSchema, TLiteralValue, TLiteral, TNumber, TInteger, TBigInt, TString, IndexerOptions, PatternNumber } from '@sinclair/typebox'
import { TObject } from '@sinclair/typebox'

const A = Indexer.Keys(Type.Number(), { includePatterns: true })
// 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]
// if (!finite && !options.includePatterns) return []
// const resolved = TemplateLiteralResolver.Resolve(schema)
// return TypeGuard.TUnionLiteral(resolved) ? resolved.anyOf.map((schema) => schema.const.toString()) : []
// }

const B = Accessor.Resolve(
Type.Object({
x: Type.Number(),
}),
A,
)
// --------------------------------------------------------------------------
// TIndexer
// --------------------------------------------------------------------------
export type TIndexerTemplateLiteral<T extends TTemplateLiteral, F = IsTemplateLiteralFiniteCheck<T>> = F extends true ? UnionToTuple<Static<T>> : []
export type TIndexerUnion<T extends TSchema[]> = T extends [infer L extends TSchema, ...infer R extends TSchema[]] ? [...TIndexer<L>, ...TIndexerUnion<R>] : []
export type TIndexerLiteral<T extends TLiteralValue> = T extends PropertyKey ? [T] : []
// 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> ? TIndexerLiteral<S> :
T extends TNumber ? ['number'] : // tuple + array indexing
T extends TInteger ? ['number'] : // tuple + array indexing
[]

console.log(A, B)
export namespace Indexer {
function TTemplateLiteral(schema: TTemplateLiteral): string[] {
const expression = TemplateLiteralParser.ParseExact(schema.pattern)
const finite = TemplateLiteralFinite.Check(expression)
if (!finite) return []
const resolved = TemplateLiteralResolver.Resolve(schema)
return TypeGuard.TUnionLiteral(resolved) ? resolved.anyOf.map((schema) => schema.const.toString()) : []
}
function Union(schema: TSchema[]): string[] {
const [L, ...R] = schema
return (schema.length > 0) ? [...Keys(L), ...Union(R)] : []
}
function TLiteral(schema: TLiteral): string[] {
return [schema.const.toString()]
}
function Visit(schema: TSchema) {
return (
TypeGuard.TTemplateLiteral(schema) ? TTemplateLiteral(schema) :
TypeGuard.TUnion(schema) ? Union(schema.anyOf) :
TypeGuard.TLiteral(schema) ? TLiteral(schema) :
TypeGuard.TNumber(schema) ? ['number'] : // tuple + array indexing
TypeGuard.TInteger(schema) ? ['number'] : // tuple + array indexing
[]
)
}
export function Pattern(schema: TSchema) {
const keys = Keys(schema)
const pattern = keys.map((key) => key === 'number' ? PatternNumber : key)
return `^(${pattern.join('|')})$`
}
export function Keys(schema: TSchema) {
return [...new Set(Visit(schema))]
}
}

const K = Indexer.Pattern(Type.Union([
Type.String(),
Type.Number(),
Type.String()
]))



console.log(K)

// export interface IndexerOptions {
// includePatterns: boolean
// }
// // prettier-ignore
// export namespace Indexer {
// function UnwrapPattern(key: string) {
// return key[0] === '^' && key[key.length - 1] === '$' ? key.slice(1, key.length - 1) : key
// }

// function TIntersect(schema: TIntersect, options: IndexerOptions): string[] {
// return schema.allOf.reduce((acc, schema) => [...acc, ...Visit(schema, options)], [] as string[])
// }
// function TUnion(schema: TUnion, options: IndexerOptions): string[] {
// const sets = schema.anyOf.reduce((acc, schema) => [...acc, ...Visit(schema, options)], [] as string[])
// console.log('Accessor Union', sets)
// return [...sets.reduce((set, outer) => outer.map((key) => (sets.every((inner) => inner.includes(key)) ? set.add(key) : set))[0], new Set<string>())]
// }
// function TObject(schema: TObject, options: IndexerOptions): string[] {
// return Object.getOwnPropertyNames(schema.properties)
// }
// function TRecord(schema: TRecord, options: IndexerOptions): string[] {
// return options.includePatterns ? Object.getOwnPropertyNames(schema.patternProperties) : []
// }
// function TLiteral(schema: TLiteral, options: IndexerOptions): string[] {
// return [schema.const.toString()]
// }
// 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[] {
// 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) :
// TypeGuard.TLiteral(schema) ? TLiteral(schema, options) :
// TypeGuard.TInteger(schema) ? TInteger(schema, options) :
// TypeGuard.TNumber(schema) ? TNumber(schema, options) :
// []
// )
// }
// /** Resolves a regular expression pattern matching all keys in this schema */
// 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[] {
// console.log('Indexer', Visit(schema, options))
// return [...new Set(Visit(schema, options))]
// }
// }

// const T = Type.Object({
// 0: Type.Number(),
// 1: Type.String(),
// 2: Type.Boolean(),
// })
// const I = Type.Index(T, Type.Union([Type.Literal(0), Type.Literal(2)]))

// console.log(I)
17 changes: 0 additions & 17 deletions src/typebox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3058,23 +3058,6 @@ export class JsonTypeBuilder extends TypeBuilder {
this.Never(options)
) as TExtract<L, R>
}
// /** `[Json]` Returns an Indexed property type for the given keys */
// public Index<T extends TArray, K extends TNumber>(schema: T, keys: K, options?: SchemaOptions): AssertType<T['items']>
// /** `[Json]` Returns an Indexed property type for the given keys */
// public Index<T extends TTuple, K extends (keyof Static<T>)[]>(schema: T, keys: [...K], options?: SchemaOptions): TIndex<T, Assert<K, TPropertyKey[]>>
// /** `[Json]` Returns an Indexed property type for the given keys */
// public Index<T extends TTuple, K extends TNumber>(schema: T, keys: K, options?: SchemaOptions): UnionType<AssertRest<T['items']>>
// /** `[Json]` Returns an Indexed property type for the given keys */
// public Index<T extends TSchema, K extends TTemplateLiteral>(schema: T, keys: K, options?: SchemaOptions): TIndex<T, TTemplateLiteralKeyRest<K>>
// /** `[Json]` Returns an Indexed property type for the given keys */
// public Index<T extends TSchema, K extends TLiteral<TPropertyKey>>(schema: T, keys: K, options?: SchemaOptions): TIndex<T, [K['const']]>
// /** `[Json]` Returns an Indexed property type for the given keys */
// public Index<T extends TSchema, K extends (keyof Static<T>)[]>(schema: T, keys: [...K], options?: SchemaOptions): TIndex<T, Assert<K, TPropertyKey[]>>
// /** `[Json]` Returns an Indexed property type for the given keys */
// public Index<T extends TSchema, K extends TUnion<TLiteral<TPropertyKey>[]>>(schema: T, keys: K, options?: SchemaOptions): TIndex<T, TUnionLiteralKeyRest<K>>
// /** `[Json]` Returns an Indexed property type for the given keys */
// public Index<T extends TSchema, K extends TSchema>(schema: T, key: K, options?: SchemaOptions): TSchema

/** `[Json]` Returns an Indexed property type for the given keys */
public Index<T extends TSchema, I extends TSchema, K extends PropertyKey[] = TIndexer<I>>(schema: T, keys: I, options?: SchemaOptions): TIndex<T, K>
/** `[Json]` Returns an Indexed property type for the given keys */
Expand Down

0 comments on commit 2b5fa1c

Please sign in to comment.