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 d1f203d commit 611e8ac
Show file tree
Hide file tree
Showing 8 changed files with 453 additions and 388 deletions.
148 changes: 50 additions & 98 deletions examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,102 +2,54 @@
// Accessor
// --------------------------------------------------------------------------

import { Type, Static, Distinct, Optional, TOptional, TReadonly, TObject, TTuple, TIntersect, TUnion, Kind, TSchema, TypeClone, TypeGuard, ValueGuard, TPropertyKey, SchemaOptions, TProperties, TNever, TRecursive, TArray, Discard, TNumber, TString, TBoolean } from "@sinclair/typebox"
import {
Type,
Into,
Static,
Distinct,
Optional,
TOptional,
TReadonly,
TObject,
TTuple,
TIntersect,
TUnion,
Kind,
TSchema,
TypeClone,
TypeGuard,
ValueGuard,
TPropertyKey,
SchemaOptions,
TProperties,
TNever,
TRecursive,
TArray,
Discard,
TNumber,
TString,
TBoolean,
IntersectType,
UnionType,
TemplateLiteralParser,
TemplateLiteralFinite,
TemplateLiteralResolver,
TTemplateLiteral,
TLiteral,
TInteger,
TLiteralValue,
IsTemplateLiteralFiniteCheck,
UnionToTuple,
PatternNumber
} from '@sinclair/typebox'

const T = Type.Union([
Type.Object({ x: Type.Number() }),
Type.Object({ y: Type.Number() })
])
const I = Type.Index(T, ['x'])

console.log(I)

type T = { x: 1 } | { y: 1 }

const T = Type.Object({
x: Type.Number(),
y: Type.Number(),
z: Type.Number()
})
type T = typeof T

type A = Distinct.Resolve<[TString, T]>
const A = Distinct.Resolve([Type.String(), T])
console.log(A)

// ------------------------------------------------------------------
// Accessor
// ------------------------------------------------------------------
// export type TAccessorProperty<T extends TProperties, K extends PropertyKey> = K extends keyof T ? T[K] : TNever
// export type TAccessorTuple<T extends TSchema[], K extends PropertyKey> = K extends keyof T ? T[K] : K extends 'number' ? UnionTypeResolve<T> : TNever
// export type TAccessorArray<T extends TSchema, K extends PropertyKey> = K extends number ? T : TNever
// // prettier-ignore
// export type TAccessorRest<T extends TSchema[], K extends PropertyKey> =
// T extends [infer L extends TSchema, ...infer R extends TSchema[]]
// ? TAccessorKey<L, K> extends infer N extends TSchema
// ? N extends TNever
// ? [...TAccessorRest<R, K>]
// : [N, ...TAccessorRest<R, K>]
// : []
// : []
// // prettier-ignore
// export type TAccessorKey<T extends TSchema, K extends PropertyKey> =
// T extends TRecursive<infer S> ? TAccessorKey<S, K> :
// T extends TIntersect<infer S> ? IntersectTypeResolve<TAccessorRest<S, K>> :
// T extends TUnion<infer S> ? UnionTypeResolve<TAccessorRest<S, K>> :
// T extends TTuple<infer S> ? TAccessorTuple<S, K> :
// T extends TArray<infer S> ? TAccessorArray<S, K> :
// T extends TObject<infer S> ? TAccessorProperty<S, K> :
// TNever
// // prettier-ignore
// export type TAccessorKeys<T extends TSchema, K extends PropertyKey[]> =
// K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]]
// ? [TAccessorKey<T, L>, ...TAccessorKeys<T, R>]
// : []

// export type TAccessor<T extends TSchema, K extends PropertyKey[]> = UnionTypeResolve<TAccessorKeys<T, K>>

// // prettier-ignore
// export namespace Accessor {
// function Property(T: TProperties, K: PropertyKey): TSchema {
// return K in T ? T[K as string] : Type.Never()
// }
// function Tuple(T: TSchema[], K: PropertyKey): TSchema {
// return K in T ? T[K as number] : K === 'number' ? Union.Resolve(T) : Type.Never()
// }
// function Array(T: TSchema, K: PropertyKey): TSchema {
// return K === 'number' ? T : Type.Never()
// }
// function Rest(T: TSchema[], K: PropertyKey): TSchema[] {
// const [L, ...R] = T
// return T.length > 0
// ? Into(() => {
// const N = Key(L, K)
// return TypeGuard.TNever(N)
// ? [...Rest(R, K)]
// : [N, ...Rest(R, K)]
// })
// : []
// }
// function Key(T: TSchema, K: PropertyKey) {
// return (
// TypeGuard.TIntersect(T) ? Intersect.Resolve(Rest(T.allOf, K)) :
// TypeGuard.TUnion(T) ? Union.Resolve(Rest(T.anyOf, K)) :
// TypeGuard.TTuple(T) ? Tuple(T.items ?? [], K) :
// TypeGuard.TArray(T) ? Array(T.items, K) :
// TypeGuard.TObject(T) ? Property(T.properties, K) :
// Type.Never()
// )
// }
// function Keys(T: TSchema, K: PropertyKey[]): TSchema[] {
// const [L, ...R] = K
// return (K.length > 0)
// ? [Key(T, L), ...Keys(T, R)]
// : []
// }
// export function Resolve(schema: TSchema, keys: PropertyKey[]) {
// return Union.Resolve(Keys(schema, keys))
// }
// }

// const T = Type.Composite([
// Type.Object({ x: Type.Optional(Type.Number()) }),
// Type.Object({ x: Type.Optional(Type.Number()) })
// ])

// const A = Accessor.Resolve(T, ['x'])
// const I = Type.Index(T, ['x'])



// console.log(A)
210 changes: 111 additions & 99 deletions examples/next/accessor.ts
Original file line number Diff line number Diff line change
@@ -1,101 +1,113 @@
// // --------------------------------------------------------------------------
// // Accessor
// // --------------------------------------------------------------------------
// ------------------------------------------------------------------
// Accessor
// ------------------------------------------------------------------

// import { Type, Optional, TObject, TTuple, TIntersect, TUnion, Kind, TSchema, TypeClone, TypeGuard, ValueGuard, TPropertyKey, SchemaOptions, TProperties, TNever, IntersectType, TRecursive, TArray, UnionTypeResolve } from "@sinclair/typebox"
import { IntersectType, Into, TArray, TIntersect, TNever, TObject, TProperties, TRecursive, TSchema, TTuple, TUnion, Type, TypeGuard, UnionType } from "@sinclair/typebox"

// // ------------------------------------------------------------------
// // TAccessor
// // ------------------------------------------------------------------
// export type TAccessorProperty<T extends TProperties, K extends PropertyKey> = K extends keyof T ? T[K] : TNever
// export type TAccessorTuple<T extends TSchema[], K extends PropertyKey> = K extends keyof T ? T[K] : K extends 'number' ? UnionTypeResolve<T> : TNever
// export type TAccessorArray<T extends TSchema, K extends PropertyKey> = K extends number ? T : TNever
// // prettier-ignore
// export type TAccessorRest<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
// ? [...TAccessorRest<R, K>]
// : [N, ...TAccessorRest<R, K>]
// : []
// : []
// // 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.Resolve<TAccessorRest<S, K>> :
// T extends TUnion<infer S> ? UnionTypeResolve<TAccessorRest<S, K>> :
// T extends TTuple<infer S> ? TAccessorTuple<S, K> :
// T extends TArray<infer S> ? TAccessorArray<S, K> :
// T extends TObject<infer S> ? TAccessorProperty<S, K> :
// TNever
// // prettier-ignore
// export type TAccessorKeys<T extends TSchema, K extends PropertyKey[]> =
// K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]]
// ? [TIndexKey<T, L>, ...TAccessorKeys<T, R>]
// : []

// export type TAccessor<T extends TSchema, K extends PropertyKey[]> = UnionTypeResolve<TAccessorKeys<T, K>>

// // 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) {
// 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 {
// 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))
// }
// }
// prettier-ignore
export namespace Accessor {
// ----------------------------------------------------------------
// Property
// ----------------------------------------------------------------
export type Property<T extends TProperties, K extends PropertyKey> =
K extends keyof T
? T[K]
: TNever
export function Property(T: TProperties, K: PropertyKey): TSchema {
return K in T
? T[K as string]
: Type.Never()
}
// ----------------------------------------------------------------
// Tuple
// ----------------------------------------------------------------
export type Tuple<T extends TSchema[], K extends PropertyKey> = (
K extends keyof T ? T[K] :
K extends 'number' ? UnionType.Resolve<T> :
TNever
)
export function Tuple(T: TSchema[], K: PropertyKey): TSchema {
return (
K in T ? T[K as number] :
K === 'number' ? UnionType.Resolve(T) :
Type.Never()
)
}
// ----------------------------------------------------------------
// Array
// ----------------------------------------------------------------
export type Array<T extends TSchema, K extends PropertyKey> =
K extends number
? T
: TNever
export function Array(T: TSchema, K: PropertyKey): TSchema {
return K === 'number'
? T
: Type.Never()
}
// ----------------------------------------------------------------
// Rest
// ----------------------------------------------------------------
export type Rest<T extends TSchema[], K extends PropertyKey> =
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? Key<L, K> extends infer N extends TSchema
? N extends TNever
? [...Rest<R, K>]
: [N, ...Rest<R, K>]
: []
: []
function Rest(T: TSchema[], K: PropertyKey): TSchema[] {
const [L, ...R] = T
return T.length > 0
? Into(() => {
const N = Key(L, K)
return TypeGuard.TNever(N)
? [...Rest(R, K)]
: [N, ...Rest(R, K)]
})
: []
}
// ----------------------------------------------------------------
// Key
// ----------------------------------------------------------------
export type Key<T extends TSchema, K extends PropertyKey> = (
T extends TRecursive<infer S> ? Key<S, K> :
T extends TIntersect<infer S> ? IntersectType.Resolve<Rest<S, K>> :
T extends TUnion<infer S> ? UnionType.Resolve<Rest<S, K>> :
T extends TTuple<infer S> ? Tuple<S, K> :
T extends TArray<infer S> ? Array<S, K> :
T extends TObject<infer S> ? Property<S, K> :
TNever
)
export function Key(T: TSchema, K: PropertyKey) {
return (
TypeGuard.TIntersect(T) ? IntersectType.Resolve(Rest(T.allOf, K)) :
TypeGuard.TUnion(T) ? UnionType.Resolve(Rest(T.anyOf, K)) :
TypeGuard.TTuple(T) ? Tuple(T.items ?? [], K) :
TypeGuard.TArray(T) ? Array(T.items, K) :
TypeGuard.TObject(T) ? Property(T.properties, K) :
Type.Never()
)
}
// ----------------------------------------------------------------
// Keys
// ----------------------------------------------------------------
export type Keys<T extends TSchema, K extends PropertyKey[]> =
K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]]
? [Key<T, L>, ...Keys<T, R>]
: []
export function Keys(T: TSchema, K: PropertyKey[]): TSchema[] {
const [L, ...R] = K
return (K.length > 0)
? [Key(T, L), ...Keys(T, R)]
: []
}
// ----------------------------------------------------------------
// Resolve
// ----------------------------------------------------------------
export type Resolve<T extends TSchema, K extends PropertyKey[]> =
UnionType.Resolve<Keys<T, K>>
export function Resolve(T: TSchema, K: PropertyKey[]) {
return UnionType.Resolve(Keys(T, K))
}
}
Loading

0 comments on commit 611e8ac

Please sign in to comment.