Skip to content

Commit

Permalink
Updates
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 committed Nov 16, 2024
1 parent d573edc commit 8505403
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 196 deletions.
50 changes: 11 additions & 39 deletions example/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,50 +14,22 @@ import { Type, TypeGuard, Kind, Static, TSchema } from '@sinclair/typebox'
// - Required (Computed)
// - KeyOf

//
// Todo:
// - Have more problems dealing with options not mapping over correctly. This is a
// problem for deferred types as the XRef can't be naively assign options post
// creation. I could check for these cases however.
// - Support Recursive Deref. This will be challenging, but ideally we want to
// support Partial(Required(Partial(Type.Ref('A')))). This probably means
// ditching the current XRef for a Deferred node like thing.

const M = Parse('string')

const Module = Parse(`module {
type A = {
x: number
y: number
z: number
}
type T = Required<Pick<A, 'x'>> &
Partial<Omit<A, 'x'>>
}`)

// const Module = Type.Module({
// A: Type.Partial(Type.Object({
// x: Type.Number(),
// y: Type.Number(),
// z: Type.Number(),
// })),
// T: Type.Intersect([
// Type.Required(Type.Pick(Type.Ref('A'), ['x'])),
// Type.Partial(Type.Omit(Type.Ref('A'), ['x'])),
// ])
// })

const AA = Type.Required(Type.Pick(Type.Ref('A'), ['x']))

const Module = Type.Module({
A: Type.Object({
x: Type.Number(),
y: Type.Number(),
}),
T: Type.KeyOf(Type.Ref('A')),
})

const A = Module.Import('A')
const T = Module.Import('T')

function test(value: Static<typeof T>) {}

console.dir(T, { depth: 100 })

type A = Static<typeof T>
type A = Static<typeof A>
type T = Static<typeof T>

// Ok(T, { nodes: [{ nodes: [{ nodes: [] }, { nodes: [] }] }] })

const A = Type.Omit(Type.String(), Type.Ref('A'))
31 changes: 17 additions & 14 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -1074,22 +1074,25 @@ const T = Type.Object({ // const T: TObject<{
### Module
Syntax Types support Module parsing, which is useful for processing multiple TypeScript types. Module parsing supports type alias and interface definitions. Generics are currently unsupported as of 0.34.0.
Syntax Types also support Module parsing. This can provide a more terse syntax for creating Module definitions, but comes with an inference performance cost. Module parsing supports interface and type alias definitions. Generics types are currently unsupported. Consider the following which defines a explicit Module on the left, and the parsed Module on the right.
```typescript
const Foo = Parse(`module Foo {
export type A = string
export type B = number
export type C = A | B
}`)

const C = Foo.Import('C') // const C: TImport<{
// ...
// }, 'C'>
const Module = Type.Module({ // const Module = Parse(`module {
//
User: Type.Object({ // export interface User {
id: Type.String(), // id: string
name: Type.String(), // name: string
email: Type.String(), // email: string
}), // }
//
PartialUser: Type.Intersect([ // export type PartialUser = (
Type.Pick(Type.Ref('User'), ['id']), // Pick<User, 'id'> &
Type.Partial( // Partial<Omit<User, 'id'>>
Type.Omit(Type.Ref('User'), ['id']) // )
), //
]) //
//
}) // }`)
```
<a name='syntax-context'></a>
Expand Down
1 change: 0 additions & 1 deletion src/type/keyof/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,4 @@ THE SOFTWARE.
export * from './keyof-from-mapped-result'
export * from './keyof-property-entries'
export * from './keyof-property-keys'
export * from './keyof-ref'
export * from './keyof'
20 changes: 6 additions & 14 deletions src/type/keyof/keyof-from-mapped-result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,17 @@ import type { SchemaOptions } from '../schema/index'
import type { Ensure, Evaluate } from '../helpers/index'
import type { TProperties } from '../object/index'
import { MappedResult, type TMappedResult } from '../mapped/index'
import { KeyOf, type TKeyOfUnion } from './keyof'
import { KeyOf, type TKeyOfFromType } from './keyof'
import { Clone } from '../clone/value'
// ------------------------------------------------------------------
// FromProperties
// ------------------------------------------------------------------
// prettier-ignore
type TFromProperties<
Properties extends TProperties
> = (
{ [K2 in keyof Properties]: TKeyOfUnion<Properties[K2]> }
type TFromProperties<Properties extends TProperties> = (
{ [K2 in keyof Properties]: TKeyOfFromType<Properties[K2]> }
)
// prettier-ignore
function FromProperties<
Properties extends TProperties
>(properties: Properties, options?: SchemaOptions): TFromProperties<Properties> {
function FromProperties<Properties extends TProperties>(properties: Properties, options?: SchemaOptions): TFromProperties<Properties> {
const result = {} as TProperties
for(const K2 of globalThis.Object.getOwnPropertyNames(properties)) result[K2] = KeyOf(properties[K2], Clone(options))
return result as never
Expand All @@ -53,15 +49,11 @@ function FromProperties<
// FromMappedResult
// ------------------------------------------------------------------
// prettier-ignore
type TFromMappedResult<
MappedResult extends TMappedResult
> = (
type TFromMappedResult<MappedResult extends TMappedResult> = (
Evaluate<TFromProperties<MappedResult['properties']>>
)
// prettier-ignore
function FromMappedResult<
MappedResult extends TMappedResult
>(mappedResult: MappedResult, options?: SchemaOptions): TFromMappedResult<MappedResult> {
function FromMappedResult<MappedResult extends TMappedResult>(mappedResult: MappedResult, options?: SchemaOptions): TFromMappedResult<MappedResult> {
return FromProperties(mappedResult.properties, options) as never
}
// ------------------------------------------------------------------
Expand Down
94 changes: 46 additions & 48 deletions src/type/keyof/keyof-property-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,58 +44,56 @@ import { IsIntersect, IsUnion, IsTuple, IsArray, IsObject, IsRecord } from '../g
// FromRest
// ------------------------------------------------------------------
// prettier-ignore
type TFromRest<T extends TSchema[], Acc extends PropertyKey[][] = []> = (
T extends [infer L extends TSchema, ...infer R extends TSchema[]]
? TFromRest<R, [...Acc, TKeyOfPropertyKeys<L>]>
: Acc
type TFromRest<Types extends TSchema[], Result extends PropertyKey[][] = []> = (
Types extends [infer L extends TSchema, ...infer R extends TSchema[]]
? TFromRest<R, [...Result, TKeyOfPropertyKeys<L>]>
: Result
)
// prettier-ignore
function FromRest<T extends TSchema[]>(T: [...T]): TFromRest<T> {
const Acc = [] as PropertyKey[][]
for(const L of T) Acc.push(KeyOfPropertyKeys(L))
return Acc as never
function FromRest<Types extends TSchema[]>(types: [...Types]): TFromRest<Types> {
const result = [] as PropertyKey[][]
for(const L of types) result.push(KeyOfPropertyKeys(L))
return result as never
}
// ------------------------------------------------------------------
// FromIntersect
// ------------------------------------------------------------------
// prettier-ignore
type TFromIntersect<
T extends TSchema[],
C extends PropertyKey[][] = TFromRest<T>,
R extends PropertyKey[] = TSetUnionMany<C>
> = R
type TFromIntersect<Types extends TSchema[],
PropertyKeysArray extends PropertyKey[][] = TFromRest<Types>,
PropertyKeys extends PropertyKey[] = TSetUnionMany<PropertyKeysArray>
> = PropertyKeys
// prettier-ignore
function FromIntersect<T extends TSchema[]>(T: [...T]): TFromIntersect<T> {
const C = FromRest(T) as PropertyKey[][]
const R = SetUnionMany(C)
return R as never
function FromIntersect<Types extends TSchema[]>(types: [...Types]): TFromIntersect<Types> {
const propertyKeysArray = FromRest(types) as PropertyKey[][]
const propertyKeys = SetUnionMany(propertyKeysArray)
return propertyKeys as never
}
// ------------------------------------------------------------------
// FromUnion
// ------------------------------------------------------------------
// prettier-ignore
type TFromUnion<
T extends TSchema[],
C extends PropertyKey[][] = TFromRest<T>,
R extends PropertyKey[] = TSetIntersectMany<C>
> = R
type TFromUnion<Types extends TSchema[],
PropertyKeysArray extends PropertyKey[][] = TFromRest<Types>,
PropertyKeys extends PropertyKey[] = TSetIntersectMany<PropertyKeysArray>
> = PropertyKeys
// prettier-ignore
function FromUnion<T extends TSchema[]>(T: [...T]): TFromUnion<T> {
const C = FromRest(T) as PropertyKey[][]
const R = SetIntersectMany(C)
return R as never
function FromUnion<Types extends TSchema[]>(types: [...Types]): TFromUnion<Types> {
const propertyKeysArray = FromRest(types) as PropertyKey[][]
const propertyKeys = SetIntersectMany(propertyKeysArray)
return propertyKeys as never
}
// ------------------------------------------------------------------
// FromTuple
// ------------------------------------------------------------------
// prettier-ignore
type TFromTuple<T extends TSchema[], I extends string = ZeroString, Acc extends PropertyKey[] = []> =
T extends [infer _ extends TSchema, ...infer R extends TSchema[]]
? TFromTuple<R, TIncrement<I>, [...Acc, I]>
type TFromTuple<Types extends TSchema[], Indexer extends string = ZeroString, Acc extends PropertyKey[] = []> =
Types extends [infer _ extends TSchema, ...infer R extends TSchema[]]
? TFromTuple<R, TIncrement<Indexer>, [...Acc, Indexer]>
: Acc
// prettier-ignore
function FromTuple<T extends TSchema[]>(T: [...T]): TFromTuple<T> {
return T.map((_, I) => I.toString()) as never
function FromTuple<Types extends TSchema[]>(types: [...Types]): TFromTuple<Types> {
return types.map((_, indexer) => indexer.toString()) as never
}
// ------------------------------------------------------------------
// FromArray
Expand All @@ -114,11 +112,11 @@ function FromArray<_ extends TSchema>(_: _): TFromArray<_> {
// FromProperties
// ------------------------------------------------------------------
// prettier-ignore
type TFromProperties<T extends TProperties> = (
UnionToTuple<keyof T>
type TFromProperties<Properties extends TProperties> = (
UnionToTuple<keyof Properties>
)
// prettier-ignore
function FromProperties<T extends TProperties>(T: T): TFromProperties<T> {
function FromProperties<Properties extends TProperties>(T: Properties): TFromProperties<Properties> {
return (
globalThis.Object.getOwnPropertyNames(T)
) as never
Expand All @@ -140,25 +138,25 @@ function FromPatternProperties(patternProperties: Record<PropertyKey, TSchema>):
// KeyOfPropertyKeys
// ------------------------------------------------------------------
// prettier-ignore
export type TKeyOfPropertyKeys<T extends TSchema> = (
T extends TRecursive<infer S> ? TKeyOfPropertyKeys<S> :
T extends TIntersect<infer S> ? TFromIntersect<S> :
T extends TUnion<infer S> ? TFromUnion<S> :
T extends TTuple<infer S> ? TFromTuple<S> :
T extends TArray<infer S> ? TFromArray<S> :
T extends TObject<infer S> ? TFromProperties<S> :
export type TKeyOfPropertyKeys<Type extends TSchema> = (
Type extends TRecursive<infer Type extends TSchema> ? TKeyOfPropertyKeys<Type> :
Type extends TIntersect<infer Types extends TSchema[]> ? TFromIntersect<Types> :
Type extends TUnion<infer Types extends TSchema[]> ? TFromUnion<Types> :
Type extends TTuple<infer Types extends TSchema[]> ? TFromTuple<Types> :
Type extends TArray<infer Type extends TSchema> ? TFromArray<Type> :
Type extends TObject<infer Properties extends TProperties> ? TFromProperties<Properties> :
[]
)
/** Returns a tuple of PropertyKeys derived from the given TSchema. */
// prettier-ignore
export function KeyOfPropertyKeys<T extends TSchema>(T: T): TKeyOfPropertyKeys<T> {
export function KeyOfPropertyKeys<Type extends TSchema>(type: Type): TKeyOfPropertyKeys<Type> {
return (
IsIntersect(T) ? FromIntersect(T.allOf) :
IsUnion(T) ? FromUnion(T.anyOf) :
IsTuple(T) ? FromTuple(T.items ?? []) :
IsArray(T) ? FromArray(T.items) :
IsObject(T) ? FromProperties(T.properties) :
IsRecord(T) ? FromPatternProperties(T.patternProperties) :
IsIntersect(type) ? FromIntersect(type.allOf) :
IsUnion(type) ? FromUnion(type.anyOf) :
IsTuple(type) ? FromTuple(type.items ?? []) :
IsArray(type) ? FromArray(type.items) :
IsObject(type) ? FromProperties(type.properties) :
IsRecord(type) ? FromPatternProperties(type.patternProperties) :
[]
) as never
}
Expand Down
41 changes: 0 additions & 41 deletions src/type/keyof/keyof-ref.ts

This file was deleted.

Loading

0 comments on commit 8505403

Please sign in to comment.