diff --git a/example/prototypes/evaluate.ts b/example/prototypes/evaluate.ts deleted file mode 100644 index 460d86773..000000000 --- a/example/prototypes/evaluate.ts +++ /dev/null @@ -1,134 +0,0 @@ -/*-------------------------------------------------------------------------- - -@sinclair/typebox/prototypes - -The MIT License (MIT) - -Copyright (c) 2017-2024 Haydn Paterson (sinclair) - -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 = ( - Static extends Static ? - Static extends Static ? R : - Static extends Static ? L : - TNever : - Static extends Static ? R : - TNever -) -// prettier-ignore -export type TEvaluateIntersectRest = - T extends [infer L, infer R, ...infer Rest] ? TEvaluateIntersectRest<[TEvaluateIntersectType, AssertType>, ...AssertRest]> : - T -// prettier-ignore -export type TEvaluateProperties = Evaluate<{ - [K in keyof T]: TEvaluate -}> -// prettier-ignore -export type TEvaluateArray = T extends [infer L, ...infer R] ? - [TEvaluate>, ...TEvaluateArray>] : - [] -// prettier-ignore -export type TEvaluate = - T extends TIntersect ? TIntersect> : - T extends TUnion ? TUnion> : - T extends TConstructor ? TConstructor, TEvaluate> : - T extends TFunction ? TFunction, TEvaluate> : - T extends TObject ? TObject> : - T extends TTuple ? TTuple> : - T extends TArray ? TArray> : - T extends TPromise ? TPromise> : - T extends TIterator ? TIterator> : - T extends TAsyncIterator ? TAsyncIterator> : - T -// -------------------------------------------------------------------------- -// Evaluate -// -------------------------------------------------------------------------- -// prettier-ignore -export function EvaluateIntersectType(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: [...T]): TEvaluateIntersectRest { - 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(properties: T) { - return Object.getOwnPropertyNames(properties).reduce((acc, key) => { - return { ...acc, [key]: Evaluate(properties[key]) } - }, {} as TProperties) -} -export function EvaluateArray(rest: T) { - if (rest === undefined) return [] // for tuple items - return rest.map((schema) => Evaluate(schema)) -} -// prettier-ignore -export function Evaluate(schema: T): TEvaluate { - 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 -} - diff --git a/example/prototypes/index.ts b/example/prototypes/index.ts index 197718e48..cb81ad0bb 100644 --- a/example/prototypes/index.ts +++ b/example/prototypes/index.ts @@ -26,7 +26,6 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ -export * from './evaluate' export * from './from-schema' export * from './module' export * from './partial-deep' diff --git a/example/prototypes/mutual.ts b/example/prototypes/mutual.ts deleted file mode 100644 index c47b7c798..000000000 --- a/example/prototypes/mutual.ts +++ /dev/null @@ -1,48 +0,0 @@ -/*-------------------------------------------------------------------------- - -@sinclair/typebox/prototypes - -The MIT License (MIT) - -Copyright (c) 2017-2024 Haydn Paterson (sinclair) - -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 = (reference: T) => Type.Object({ - b: Type.Union([reference, Type.Null()]) -}, { additionalProperties: false }) - -const __B = (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; -type B = Static; - diff --git a/example/prototypes/readme.md b/example/prototypes/readme.md index 77a962c70..48c1bf980 100644 --- a/example/prototypes/readme.md +++ b/example/prototypes/readme.md @@ -1,48 +1,44 @@ # 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` TypeScript utility type, but as TypeBox uses this name as a property modifier, the name `Const` is used. - -```typescript -import { Const } from './prototypes' - -const T = Const(Type.Object({ // const T: TObject<{ - x: Type.Number() // x: Type.Readonly(Type.Number()) -})) // }> - -type T = Static // type T = { - // readonly x: number - // } -``` -## Evaluate - -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. +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 instances via `M.Import(...)` which constructs a `$def` schematic containing each definition required to validate, but a self referential `$ref` to the type being imported. ```typescript -import { Evaluate } from './prototypes' +import { Module, ModuleRef } from './prototypes' -// Evaluate for Duplicates -// -const T = Type.Intersect([ Type.Number(), Type.Number(), Type.Number() ]) - -const E = Evaluate(T) // const E: TNumber +// A module of cross referenced Types. ModuleRef is used to cross reference. +const Math = new 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()) + }) +}) -// Evaluate for TNever -// -const T = Type.Intersect([ Type.Number(), Type.String() ]) +// Types must be imported from the Module. +const Vector2 = Math.Import('Vector2') -const E = Evaluate(T) // const E: TIntersect<[TNumber, TString]> +const Vector3 = Math.Import('Vector2') -// Evaluate for most narrowed type -// -const T = Type.Intersect([ Type.Number(), Type.Literal(1) ]) +const Vertex = Math.Import('Vertex') -const E = Evaluate(T) // const E: TLiteral<1> +const Geometry = Math.Import('Geometry') ``` ## PartialDeep