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 8eb67ba commit e1dc6fa
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 27 deletions.
11 changes: 2 additions & 9 deletions example/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { Type, Index, TypeGuard, Kind, Static, TSchema } from '@sinclair/typebox
// - Index (Computed ... mostly (needs rewrite))
// - Record (Computed)


// const Module = Parse(`module {

// type A = {
Expand All @@ -24,7 +23,7 @@ import { Type, Index, TypeGuard, Kind, Static, TSchema } from '@sinclair/typebox
// }

// type K = A[keyof A]

// }`)

const Module = Type.Module({
Expand All @@ -33,14 +32,8 @@ const Module = Type.Module({
// x: Type.Number(),
// y: Type.Number()
// }),
Z: Type.Partial(Type.Ref('T'))
Z: Type.Partial(Type.Ref('T')),
})

const T = Module.Import('Z')
type T = Static<typeof T>






15 changes: 6 additions & 9 deletions src/type/module/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

import { Evaluate } from '../helpers/index'
import { CreateType } from '../create/index'
import { Kind } from '../symbols/index'
import { SchemaOptions, TSchema } from '../schema/index'
Expand All @@ -36,11 +35,9 @@ import { Static } from '../static/index'
// ------------------------------------------------------------------
// Module Infrastructure Types
// ------------------------------------------------------------------
import { ComputeType, type TComputeType } from './compute'
import { type TComputeType } from './compute'
import { ComputeModuleProperties, TComputeModuleProperties } from './compute'

import { TInferType } from './infer'
import { TNever } from '../never'

// ------------------------------------------------------------------
// Definitions
Expand All @@ -53,10 +50,10 @@ export interface TDefinitions<ModuleProperties extends TProperties> extends TSch
// Import
// ------------------------------------------------------------------
// prettier-ignore
export interface TImport<ModuleProperties extends TProperties = {}, Key extends PropertyKey = PropertyKey> extends TSchema {
export interface TImport<ModuleProperties extends TProperties = {}, Key extends keyof ModuleProperties = keyof ModuleProperties> extends TSchema {
[Kind]: 'Import'
static: TInferType<ModuleProperties, Key>
$defs: TComputeType<ModuleProperties, Key>
$defs: TComputeModuleProperties<ModuleProperties>
$ref: Key
}
// ------------------------------------------------------------------
Expand All @@ -71,14 +68,14 @@ export class TModule<ModuleProperties extends TProperties, ComputedModulePropert
this.$defs = identified as never
}
/** `[Json]` Imports a Type by Key. */
public Import<Key extends keyof ModuleProperties>(key: Key, options?: SchemaOptions): TImport<ComputedModuleProperties, Key> {
public Import<Key extends keyof ComputedModuleProperties>(key: Key, options?: SchemaOptions): TImport<ComputedModuleProperties, Key> {
return CreateType({ [Kind]: 'Import', $defs: this.$defs, $ref: key }, options) as never
}
// prettier-ignore
private WithIdentifiers($defs: ModuleProperties) {
private WithIdentifiers($defs: ComputedModuleProperties): ComputedModuleProperties {
return globalThis.Object.getOwnPropertyNames($defs).reduce((result, key) => {
return { ...result, [key]: { ...$defs[key], $id: key }}
}, {})
}, {}) as never
}
}
/** `[Json]` Creates a Type Definition Module. */
Expand Down
151 changes: 146 additions & 5 deletions test/runtime/type/guard/kind/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,155 @@ import { KindGuard } from '@sinclair/typebox'
import { Type } from '@sinclair/typebox'
import { Assert } from '../../../assert/index'

describe('guard/type/TImport', () => {
describe('guard/kind/TImport', () => {
it('Should guard for TImport', () => {
const M = Type.Module({
const Module = Type.Module({
A: Type.String(),
})
const I = M.Import('A')
const N = I.$defs[I.$ref]
Assert.IsTrue(KindGuard.IsImport(I))
const A = Module.Import('A')
const N = A.$defs[A.$ref]
Assert.IsTrue(KindGuard.IsImport(A))
Assert.IsTrue(KindGuard.IsString(N))
})
// ----------------------------------------------------------------
// Computed: Awaited
// ----------------------------------------------------------------
it('Should compute for Awaited', () => {
const Module = Type.Module({
T: Type.Promise(Type.String()),
R: Type.Awaited(Type.Ref('T')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsString(T.$defs['R']))
})
// ----------------------------------------------------------------
// Computed: Index (Note: Pending Reimplementation of Index)
// ----------------------------------------------------------------
it('Should compute for Index 2', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.String() }),
I: Type.Literal('x'),
R: Type.Index(Type.Ref('T'), Type.Ref('I')) as never, // fail
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R']))
})
// ----------------------------------------------------------------
// Computed: Omit
// ----------------------------------------------------------------
it('Should compute for Omit 1', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.Number() }),
R: Type.Omit(Type.Ref('T'), Type.Literal('x')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.y))
// @ts-ignore
Assert.IsTrue(T.$defs['R'].properties.x === undefined)
})
it('Should compute for Omit 2', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.Number() }),
K: Type.Literal('x'),
R: Type.Omit(Type.Ref('T'), Type.Ref('K')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.y))
// @ts-ignore
Assert.IsTrue(T.$defs['R'].properties.x === undefined)
})
// ----------------------------------------------------------------
// Computed: Partial
// ----------------------------------------------------------------
it('Should compute for Partial', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number() }),
R: Type.Partial(Type.Ref('T')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x))
Assert.IsTrue(KindGuard.IsOptional(T.$defs['R'].properties.x))
})
// ----------------------------------------------------------------
// Computed: Pick
// ----------------------------------------------------------------
it('Should compute for Pick 1', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.Number() }),
R: Type.Pick(Type.Ref('T'), Type.Literal('x')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x))
// @ts-ignore
Assert.IsTrue(T.$defs['R'].properties.y === undefined)
})
it('Should compute for Pick 2', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.Number() }),
K: Type.Literal('x'),
R: Type.Pick(Type.Ref('T'), Type.Ref('K')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x))
// @ts-ignore
Assert.IsTrue(T.$defs['R'].properties.y === undefined)
})
// ----------------------------------------------------------------
// Computed: Record
// ----------------------------------------------------------------
it('Should compute for Record 1', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.String() }),
R: Type.Record(Type.String(), Type.Ref('T')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsRecord(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].patternProperties['^(.*)$'].properties.x))
Assert.IsTrue(KindGuard.IsString(T.$defs['R'].patternProperties['^(.*)$'].properties.y))
})
it('Should compute for Record 2', () => {
const Module = Type.Module({
T: Type.Number(),
K: Type.Union([Type.Literal('x'), Type.Literal('y')]),
R: Type.Record(Type.Ref('K'), Type.Ref('T')),
})
const T = Module.Import('R')
console.log(T.$defs['R'])
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x))
})
// ----------------------------------------------------------------
// Computed: Required
// ----------------------------------------------------------------
it('Should compute for Required', () => {
const Module = Type.Module({
T: Type.Partial(Type.Object({ x: Type.Number() })),
R: Type.Required(Type.Ref('T')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsObject(T.$defs['R']))
Assert.IsTrue(KindGuard.IsNumber(T.$defs['R'].properties.x))
Assert.IsFalse(KindGuard.IsOptional(T.$defs['R'].properties.x))
})
// ----------------------------------------------------------------
// Computed: KeyOf
// ----------------------------------------------------------------
it('Should compute for KeyOf', () => {
const Module = Type.Module({
T: Type.Object({ x: Type.Number(), y: Type.String() }),
R: Type.KeyOf(Type.Ref('T')),
})
const T = Module.Import('R')
Assert.IsTrue(KindGuard.IsUnion(T.$defs['R']))
Assert.IsTrue(KindGuard.IsLiteral(T.$defs['R'].anyOf[0]))
Assert.IsTrue(KindGuard.IsLiteral(T.$defs['R'].anyOf[1]))
Assert.IsTrue(T.$defs['R'].anyOf[0].const === 'x')
Assert.IsTrue(T.$defs['R'].anyOf[1].const === 'y')
})
})
Loading

0 comments on commit e1dc6fa

Please sign in to comment.