mirror of
https://github.com/zoriya/typebox.git
synced 2026-05-30 09:50:21 +00:00
Module Prototype (#1016)
* Add Module Prototype * Discard Evaluate and Mutual Prototypes * Update Prototype Readme
This commit is contained in:
@@ -1,134 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/prototypes
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import {
|
||||
AssertRest,
|
||||
AssertType,
|
||||
Static,
|
||||
Type,
|
||||
TypeGuard,
|
||||
TSchema,
|
||||
TObject,
|
||||
Evaluate,
|
||||
TArray,
|
||||
TFunction,
|
||||
TConstructor,
|
||||
TPromise,
|
||||
TIterator,
|
||||
TAsyncIterator,
|
||||
TTuple,
|
||||
TProperties,
|
||||
TIntersect,
|
||||
TUnion,
|
||||
TNever
|
||||
} from '@sinclair/typebox'
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// TEvaluate
|
||||
// --------------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type TEvaluateIntersectType<L extends TSchema, R extends TSchema> = (
|
||||
Static<L> extends Static<R> ?
|
||||
Static<R> extends Static<L> ? R :
|
||||
Static<L> extends Static<R> ? L :
|
||||
TNever :
|
||||
Static<R> extends Static<L> ? R :
|
||||
TNever
|
||||
)
|
||||
// prettier-ignore
|
||||
export type TEvaluateIntersectRest<T extends TSchema[]> =
|
||||
T extends [infer L, infer R, ...infer Rest] ? TEvaluateIntersectRest<[TEvaluateIntersectType<AssertType<L>, AssertType<R>>, ...AssertRest<Rest>]> :
|
||||
T
|
||||
// prettier-ignore
|
||||
export type TEvaluateProperties<T extends TProperties> = Evaluate<{
|
||||
[K in keyof T]: TEvaluate<T[K]>
|
||||
}>
|
||||
// prettier-ignore
|
||||
export type TEvaluateArray<T extends TSchema[]> = T extends [infer L, ...infer R] ?
|
||||
[TEvaluate<AssertType<L>>, ...TEvaluateArray<AssertRest<R>>] :
|
||||
[]
|
||||
// prettier-ignore
|
||||
export type TEvaluate<T extends TSchema> =
|
||||
T extends TIntersect<infer S> ? TIntersect<TEvaluateIntersectRest<S>> :
|
||||
T extends TUnion<infer S> ? TUnion<TEvaluateArray<S>> :
|
||||
T extends TConstructor<infer P, infer R> ? TConstructor<TEvaluateArray<P>, TEvaluate<R>> :
|
||||
T extends TFunction<infer P, infer R> ? TFunction<TEvaluateArray<P>, TEvaluate<R>> :
|
||||
T extends TObject<infer S> ? TObject<TEvaluateProperties<S>> :
|
||||
T extends TTuple<infer S> ? TTuple<TEvaluateArray<S>> :
|
||||
T extends TArray<infer S> ? TArray<TEvaluate<S>> :
|
||||
T extends TPromise<infer S> ? TPromise<TEvaluate<S>> :
|
||||
T extends TIterator<infer S> ? TIterator<TEvaluate<S>> :
|
||||
T extends TAsyncIterator<infer S> ? TAsyncIterator<TEvaluate<S>> :
|
||||
T
|
||||
// --------------------------------------------------------------------------
|
||||
// Evaluate
|
||||
// --------------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export function EvaluateIntersectType<X extends TSchema, Y extends TSchema>(L: X, R: Y) {
|
||||
return Type.Extends(L, R,
|
||||
Type.Extends(R, L, R,
|
||||
Type.Extends(L, R, L,
|
||||
Type.Never())),
|
||||
Type.Extends(R, L, R,
|
||||
Type.Never()))
|
||||
}
|
||||
// prettier-ignore
|
||||
export function EvaluateIntersectRest<T extends TSchema[]>(T: [...T]): TEvaluateIntersectRest<T> {
|
||||
if(T.length >= 2) {
|
||||
const [L, R, ...Rest] = T
|
||||
return EvaluateIntersectRest([EvaluateIntersectType(L, R), ...Rest]) as any
|
||||
} else {
|
||||
return T as any
|
||||
}
|
||||
}
|
||||
export function EvaluateProperties<T extends TProperties>(properties: T) {
|
||||
return Object.getOwnPropertyNames(properties).reduce((acc, key) => {
|
||||
return { ...acc, [key]: Evaluate(properties[key]) }
|
||||
}, {} as TProperties)
|
||||
}
|
||||
export function EvaluateArray<T extends TSchema[] | undefined>(rest: T) {
|
||||
if (rest === undefined) return [] // for tuple items
|
||||
return rest.map((schema) => Evaluate(schema))
|
||||
}
|
||||
// prettier-ignore
|
||||
export function Evaluate<T extends TSchema>(schema: T): TEvaluate<T> {
|
||||
return (
|
||||
TypeGuard.IsIntersect(schema) ? Type.Intersect(EvaluateIntersectRest(schema.allOf)) :
|
||||
TypeGuard.IsUnion(schema) ? Type.Union(EvaluateArray(schema.anyOf)) :
|
||||
TypeGuard.IsAsyncIterator(schema) ? Type.AsyncIterator(Evaluate(schema.items)) :
|
||||
TypeGuard.IsIterator(schema) ? Type.Iterator(Evaluate(schema.items)) :
|
||||
TypeGuard.IsObject(schema) ? Type.Object(EvaluateProperties(schema.properties)) :
|
||||
TypeGuard.IsConstructor(schema) ? Type.Constructor(EvaluateArray(schema.parameters), Evaluate(schema.returns)) :
|
||||
TypeGuard.IsFunction(schema) ? Type.Function(EvaluateArray(schema.parameters), Evaluate(schema.returns)) :
|
||||
TypeGuard.IsTuple(schema) ? Type.Tuple(EvaluateArray(schema.items)) :
|
||||
TypeGuard.IsArray(schema) ? Type.Promise(Evaluate(schema.items)) :
|
||||
TypeGuard.IsPromise(schema) ? Type.Promise(Evaluate(schema.item)) :
|
||||
schema
|
||||
) as TEvaluate<T>
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@ THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
export * from './evaluate'
|
||||
export * from './from-schema'
|
||||
export * from './module'
|
||||
export * from './partial-deep'
|
||||
export * from './union-enum'
|
||||
export * from './union-oneof'
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/prototypes
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import * as Types from '@sinclair/typebox'
|
||||
import { Check } from '@sinclair/typebox/value'
|
||||
// ------------------------------------------------------------------
|
||||
// Infer
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export type InferImport<Properties extends TModuleProperties, Key extends keyof Properties, Module extends TModuleProperties> = (
|
||||
Infer<Properties[Key], Module>
|
||||
)
|
||||
// prettier-ignore
|
||||
export type InferModuleRef<Ref extends string, Module extends TModuleProperties> = (
|
||||
Ref extends keyof Module ? Infer<Module[Ref], Module> : never
|
||||
)
|
||||
// prettier-ignore
|
||||
export type InferObject<Properties extends Types.TProperties, Module extends TModuleProperties> = {
|
||||
[K in keyof Properties]: Infer<Properties[K], Module>
|
||||
} & {}
|
||||
// prettier-ignore
|
||||
export type InferConstructor<Parameters extends Types.TSchema[], InstanceType extends Types.TSchema, Module extends TModuleProperties> = Types.Ensure<
|
||||
new (...args: InferTuple<Parameters, Module>) => Infer<InstanceType, Module>
|
||||
>
|
||||
// prettier-ignore
|
||||
export type InferFunction<Parameters extends Types.TSchema[], ReturnType extends Types.TSchema, Module extends TModuleProperties> = Types.Ensure<
|
||||
(...args: InferTuple<Parameters, Module>) => Infer<ReturnType, Module>
|
||||
>
|
||||
// prettier-ignore
|
||||
export type InferTuple<Types extends Types.TSchema[], Module extends TModuleProperties, Result extends unknown[] = []> = (
|
||||
Types extends [infer L extends Types.TSchema, ...infer R extends Types.TSchema[]]
|
||||
? InferTuple<R, Module, [...Result, Infer<L, Module>]>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
export type InferIntersect<Types extends Types.TSchema[], Module extends TModuleProperties, Result extends unknown = unknown> = (
|
||||
Types extends [infer L extends Types.TSchema, ...infer R extends Types.TSchema[]]
|
||||
? InferIntersect<R, Module, Result & Infer<L, Module>>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
export type InferUnion<Types extends Types.TSchema[], Module extends TModuleProperties, Result extends unknown = never> = (
|
||||
Types extends [infer L extends Types.TSchema, ...infer R extends Types.TSchema[]]
|
||||
? InferUnion<R, Module, Result | Infer<L, Module>>
|
||||
: Result
|
||||
)
|
||||
// prettier-ignore
|
||||
export type InferArray<Type extends Types.TSchema, Module extends TModuleProperties> = (
|
||||
Types.Ensure<Array<Infer<Type, Module>>>
|
||||
)
|
||||
// prettier-ignore
|
||||
export type InferAsyncIterator<Type extends Types.TSchema, Module extends TModuleProperties> = (
|
||||
Types.Ensure<AsyncIterableIterator<Infer<Type, Module>>>
|
||||
)
|
||||
// prettier-ignore
|
||||
export type InferIterator<Type extends Types.TSchema, Module extends TModuleProperties> = (
|
||||
Types.Ensure<IterableIterator<Infer<Type, Module>>>
|
||||
)
|
||||
// prettier-ignore
|
||||
type Infer<Type extends Types.TSchema, Module extends TModuleProperties = {}> = (
|
||||
Type extends TImport<infer S extends TModuleProperties, infer K extends PropertyKey> ? InferImport<S, K, S> :
|
||||
Type extends TModuleRef<infer S extends string> ? InferModuleRef<S, Module> :
|
||||
Type extends Types.TObject<infer S extends Types.TProperties> ? InferObject<S, Module> :
|
||||
Type extends Types.TConstructor<infer S extends Types.TSchema[], infer R extends Types.TSchema> ? InferConstructor<S, R, Module> :
|
||||
Type extends Types.TFunction<infer S extends Types.TSchema[], infer R extends Types.TSchema> ? InferFunction<S, R, Module> :
|
||||
Type extends Types.TTuple<infer S extends Types.TSchema[]> ? InferTuple<S, Module> :
|
||||
Type extends Types.TIntersect<infer S extends Types.TSchema[]> ? InferIntersect<S, Module> :
|
||||
Type extends Types.TUnion<infer S extends Types.TSchema[]> ? InferUnion<S, Module> :
|
||||
Type extends Types.TArray<infer S extends Types.TSchema> ? InferArray<S, Module> :
|
||||
Type extends Types.TAsyncIterator<infer S extends Types.TSchema> ? InferAsyncIterator<S, Module> :
|
||||
Type extends Types.TIterator<infer S extends Types.TSchema> ? InferIterator<S, Module> :
|
||||
Type extends Types.TTemplateLiteral<infer S extends Types.TTemplateLiteralKind[]> ? Types.Static<Types.TTemplateLiteral<S>> :
|
||||
Type extends Types.TLiteral<infer S extends Types.TLiteralValue> ? S :
|
||||
Type extends Types.TAny ? any :
|
||||
Type extends Types.TBigInt ? bigint :
|
||||
Type extends Types.TBoolean ? boolean :
|
||||
Type extends Types.TDate ? Date :
|
||||
Type extends Types.TInteger ? number :
|
||||
Type extends Types.TNever ? never :
|
||||
Type extends Types.TNumber ? number :
|
||||
Type extends Types.TRegExp ? string :
|
||||
Type extends Types.TString ? string :
|
||||
Type extends Types.TSymbol ? symbol :
|
||||
Type extends Types.TNull ? null :
|
||||
Type extends Types.TUint8Array ? Uint8Array :
|
||||
Type extends Types.TUndefined ? undefined :
|
||||
Type extends Types.TUnknown ? unknown :
|
||||
Type extends Types.TVoid ? void :
|
||||
never
|
||||
)
|
||||
// ------------------------------------------------------------------
|
||||
// ModuleRef
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export interface TModuleRef<Ref extends string> extends Types.TSchema {
|
||||
[Types.Kind]: 'ModuleRef'
|
||||
$ref: Ref
|
||||
}
|
||||
// prettier-ignore
|
||||
export function ModuleRef<Ref extends string>($ref: Ref): TModuleRef<Ref> {
|
||||
return Types.Type.Ref($ref) as never
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Import
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
Types.TypeRegistry.Set('Import', (module: TImport, value: unknown) => {
|
||||
const keys = Object.getOwnPropertyNames(module.$defs)
|
||||
const references = keys.map(key => module.$defs[key as never]) as Types.TSchema[]
|
||||
const schema = module.$defs[module.$ref]
|
||||
return Check(schema, references, value)
|
||||
})
|
||||
// prettier-ignore
|
||||
export type TModuleProperties = Record<PropertyKey, Types.TSchema>
|
||||
|
||||
// prettier-ignore
|
||||
export interface TImport<Definitions extends TModuleProperties = {}, Key extends keyof Definitions = keyof Definitions> extends Types.TSchema {
|
||||
[Types.Kind]: 'Import'
|
||||
static: InferImport<Definitions, Key, Definitions>
|
||||
$defs: Definitions
|
||||
$ref: Key
|
||||
}
|
||||
// ------------------------------------------------------------------
|
||||
// Module
|
||||
// ------------------------------------------------------------------
|
||||
// prettier-ignore
|
||||
export class ModuleInstance<Properties extends TModuleProperties> {
|
||||
constructor(private readonly properties: Properties) {}
|
||||
public Import<Key extends keyof Properties>(key: Key): TImport<Properties, Key> {
|
||||
const $defs = globalThis.Object.getOwnPropertyNames(this.properties).reduce((Result, Key) => (
|
||||
{ ...Result, [Key]: { ...this.properties[Key], $id: Key }}
|
||||
), {})
|
||||
return { [Types.Kind]: 'Import', $defs, $ref: key } as never
|
||||
}
|
||||
}
|
||||
export function Module<Properties extends TModuleProperties>(properties: Properties): ModuleInstance<Properties> {
|
||||
return new ModuleInstance(properties)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
|
||||
@sinclair/typebox/prototypes
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2024 Haydn Paterson (sinclair) <haydn.developer@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
import { Type, TSchema, Static } from '@sinclair/typebox'
|
||||
|
||||
// Mutual Recursive Template
|
||||
const __A = <T extends TSchema>(reference: T) => Type.Object({
|
||||
b: Type.Union([reference, Type.Null()])
|
||||
}, { additionalProperties: false })
|
||||
|
||||
const __B = <T extends TSchema>(reference: T) => Type.Object({
|
||||
a: Type.Union([reference, Type.Null()])
|
||||
}, { additionalProperties: false })
|
||||
|
||||
// ....
|
||||
|
||||
// Mutual Recursive Types
|
||||
const A = Type.Recursive((This) => __A(__B(This)))
|
||||
const B = Type.Recursive((This) => __B(__A(This)))
|
||||
|
||||
type A = Static<typeof A>;
|
||||
type B = Static<typeof B>;
|
||||
|
||||
@@ -1,48 +1,46 @@
|
||||
# TypeBox Prototypes
|
||||
|
||||
TypeBox prototypes are a set of types that are either under consideration for inclusion into the library, or have been requested by users but cannot be added to the library either due to complexity, using schematics that fall outside the supported TypeBox or should be expressed by users via advanced type composition.
|
||||
TypeBox prototypes are a set of types that are either under consideration for inclusion into the library, or have been requested by users but cannot be added to the library either due to complexity, using schematics that fall outside the supported TypeBox or should be expressed by users via advanced type composition.
|
||||
|
||||
Each prototype is written as a standalone module that can be copied into projects and used directly, or integrated into extended type builders.
|
||||
## Module, ModuleRef and Import
|
||||
|
||||
## Const
|
||||
|
||||
This type will wrap all interior properties as `readonly` leaving the outer type unwrapped. This type is analogous to the `Readonly<T>` TypeScript utility type, but as TypeBox uses this name as a property modifier, the name `Const` is used.
|
||||
The Module type as a candidate referencing system for TypeBox. Modules enable deferred cross type referencing and support mutual recursive inference. Module types must be instanced via `M.Import(...)` which constructs a `$def` schematic containing each definition required to validate, and a self referential `$ref` to one of the type being imported.
|
||||
|
||||
```typescript
|
||||
import { Const } from './prototypes'
|
||||
import { Module, ModuleRef } from './prototypes'
|
||||
|
||||
const T = Const(Type.Object({ // const T: TObject<{
|
||||
x: Type.Number() // x: Type.Readonly(Type.Number())
|
||||
})) // }>
|
||||
// ------------------------------------------------------------------
|
||||
// Module, ModuleRef
|
||||
// ------------------------------------------------------------------
|
||||
const Math = Module({
|
||||
Vector2: Type.Object({
|
||||
x: Type.Number(),
|
||||
y: Type.Number(),
|
||||
}),
|
||||
Vector3: Type.Object({
|
||||
x: Type.Number(),
|
||||
y: Type.Number(),
|
||||
z: Type.Number()
|
||||
}),
|
||||
Vertex: Type.Object({
|
||||
position: ModuleRef('Vector3'),
|
||||
normal: ModuleRef('Vector3'),
|
||||
texcoord: ModuleRef('Vector2')
|
||||
}),
|
||||
Geometry: Type.Object({
|
||||
vertices: Type.Array(ModuleRef('Vertex')),
|
||||
indices: Type.Array(Type.Integer())
|
||||
})
|
||||
})
|
||||
|
||||
type T = Static<typeof T> // type T = {
|
||||
// readonly x: number
|
||||
// }
|
||||
```
|
||||
## Evaluate
|
||||
// ------------------------------------------------------------------
|
||||
// Import
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
This type is an advanced mapping type will evaluate for schema redundancy by reducing evaluating intersection rest arguments. This type detects if intersection would produce illogical `never`, removes duplicates and handles intersection type narrowing. This type is a strong candidate for inclusion into the TypeBox library but is pending an equivalent redundancy check for `union` rest arguments.
|
||||
|
||||
```typescript
|
||||
import { Evaluate } from './prototypes'
|
||||
|
||||
// Evaluate for Duplicates
|
||||
//
|
||||
const T = Type.Intersect([ Type.Number(), Type.Number(), Type.Number() ])
|
||||
|
||||
const E = Evaluate(T) // const E: TNumber
|
||||
|
||||
// Evaluate for TNever
|
||||
//
|
||||
const T = Type.Intersect([ Type.Number(), Type.String() ])
|
||||
|
||||
const E = Evaluate(T) // const E: TIntersect<[TNumber, TString]>
|
||||
|
||||
// Evaluate for most narrowed type
|
||||
//
|
||||
const T = Type.Intersect([ Type.Number(), Type.Literal(1) ])
|
||||
|
||||
const E = Evaluate(T) // const E: TLiteral<1>
|
||||
const Vector2 = Math.Import('Vector2')
|
||||
const Vector3 = Math.Import('Vector2')
|
||||
const Vertex = Math.Import('Vertex')
|
||||
const Geometry = Math.Import('Geometry')
|
||||
```
|
||||
|
||||
## PartialDeep
|
||||
|
||||
Reference in New Issue
Block a user