diff --git a/hammer.mjs b/hammer.mjs index 20af660ca..49faf269b 100644 --- a/hammer.mjs +++ b/hammer.mjs @@ -32,7 +32,7 @@ export async function benchmark() { // Test // ------------------------------------------------------------------------------- export async function test_typescript() { - for (const version of ['4.9.5', '5.0.4', '5.1.3', '5.1.6', '5.2.2', '5.3.2', '5.3.3', '5.4.3', '5.4.5', '5.5.2', 'next', 'latest']) { + for (const version of ['4.9.5', '5.0.4', '5.1.3', '5.1.6', '5.2.2', '5.3.2', '5.3.3', '5.4.3', '5.4.5', '5.5.2', '5.5.3', 'next', 'latest']) { await shell(`npm install typescript@${version} --no-save`) await test_static() } diff --git a/package-lock.json b/package-lock.json index f75983e2a..4b22daec6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sinclair/typebox", - "version": "0.32.35", + "version": "0.33.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sinclair/typebox", - "version": "0.32.35", + "version": "0.33.0", "license": "MIT", "devDependencies": { "@arethetypeswrong/cli": "^0.13.2", @@ -17,7 +17,7 @@ "ajv-formats": "^2.1.1", "mocha": "^10.4.0", "prettier": "^2.7.1", - "typescript": "^5.5.3" + "typescript": "^5.5.4" } }, "node_modules/@andrewbranch/untar.js": { @@ -1576,9 +1576,9 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -2738,9 +2738,9 @@ "dev": true }, "typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true }, "undici-types": { diff --git a/package.json b/package.json index 967cc46e0..bfe38dad3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sinclair/typebox", - "version": "0.32.35", + "version": "0.33.0", "description": "Json Schema Type Builder with Static Type Resolution for TypeScript", "keywords": [ "typescript", @@ -37,6 +37,6 @@ "ajv-formats": "^2.1.1", "mocha": "^10.4.0", "prettier": "^2.7.1", - "typescript": "^5.5.3" + "typescript": "^5.5.4" } } diff --git a/src/index.ts b/src/index.ts index dbbe67127..b88ad07ea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,6 +30,7 @@ THE SOFTWARE. // Infrastructure // ------------------------------------------------------------------ export * from './type/clone/index' +export * from './type/create/index' export * from './type/error/index' export * from './type/guard/index' export * from './type/helpers/index' diff --git a/src/system/policy.ts b/src/system/policy.ts index 400c74b16..93a68f809 100644 --- a/src/system/policy.ts +++ b/src/system/policy.ts @@ -30,9 +30,20 @@ import { IsObject, IsArray, IsNumber, IsUndefined } from '../value/guard/index' export namespace TypeSystemPolicy { // ------------------------------------------------------------------ - // TypeSystemPolicy + // TypeSystemPolicy: Instancing + // ------------------------------------------------------------------ + /** + * Configures the instantiation behavior of TypeBox types. The `default` option assigns raw JavaScript + * references for embedded types, which may cause side effects if type properties are explicitly updated + * outside the TypeBox type builder. The `clone` option creates copies of any shared types upon creation, + * preventing unintended side effects. The `freeze` option applies `Object.freeze()` to the type, making + * it fully readonly and immutable. Implementations should use `default` whenever possible, as it is the + * fastest way to instantiate types. The default setting is `default`. + */ + export let InstanceMode: 'default' | 'clone' | 'freeze' = 'default' + // ------------------------------------------------------------------ + // TypeSystemPolicy: Checking // ------------------------------------------------------------------ - /** Shared assertion routines used by the value and errors modules */ /** Sets whether TypeBox should assert optional properties using the TypeScript `exactOptionalPropertyTypes` assertion policy. The default is `false` */ export let ExactOptionalPropertyTypes: boolean = false /** Sets whether arrays should be treated as a kind of objects. The default is `false` */ diff --git a/src/type/any/any.ts b/src/type/any/any.ts index 90eaf93ec..f5d7d907c 100644 --- a/src/type/any/any.ts +++ b/src/type/any/any.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/index' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -35,6 +36,6 @@ export interface TAny extends TSchema { } /** `[Json]` Creates an Any type */ -export function Any(options: SchemaOptions = {}): TAny { - return { ...options, [Kind]: 'Any' } as never +export function Any(options?: SchemaOptions): TAny { + return CreateType({ [Kind]: 'Any' }, options) as never } diff --git a/src/type/array/array.ts b/src/type/array/array.ts index fecf073db..388ba25d7 100644 --- a/src/type/array/array.ts +++ b/src/type/array/array.ts @@ -26,7 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ -import { CloneType } from '../clone/type' +import { CreateType } from '../create/type' import { Ensure } from '../helpers/index' import type { SchemaOptions, TSchema } from '../schema/index' import type { Static } from '../static/index' @@ -54,11 +54,6 @@ export interface TArray extends TSchema, ArrayOptio items: T } /** `[Json]` Creates an Array type */ -export function Array(schema: T, options: ArrayOptions = {}): TArray { - return { - ...options, - [Kind]: 'Array', - type: 'array', - items: CloneType(schema), - } as never +export function Array(items: T, options?: ArrayOptions): TArray { + return CreateType({ [Kind]: 'Array', type: 'array', items }, options) as never } diff --git a/src/type/async-iterator/async-iterator.ts b/src/type/async-iterator/async-iterator.ts index ee9417421..2a97d73a0 100644 --- a/src/type/async-iterator/async-iterator.ts +++ b/src/type/async-iterator/async-iterator.ts @@ -29,7 +29,7 @@ THE SOFTWARE. import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import { Kind } from '../symbols/index' -import { CloneType } from '../clone/type' +import { CreateType } from '../create/type' export interface TAsyncIterator extends TSchema { [Kind]: 'AsyncIterator' @@ -38,11 +38,6 @@ export interface TAsyncIterator extends TSchema { items: T } /** `[JavaScript]` Creates a AsyncIterator type */ -export function AsyncIterator(items: T, options: SchemaOptions = {}): TAsyncIterator { - return { - ...options, - [Kind]: 'AsyncIterator', - type: 'AsyncIterator', - items: CloneType(items), - } as never +export function AsyncIterator(items: T, options?: SchemaOptions): TAsyncIterator { + return CreateType({ [Kind]: 'AsyncIterator', type: 'AsyncIterator', items }, options) as never } diff --git a/src/type/awaited/awaited.ts b/src/type/awaited/awaited.ts index 5318d98ea..e129b6a52 100644 --- a/src/type/awaited/awaited.ts +++ b/src/type/awaited/awaited.ts @@ -30,7 +30,7 @@ import type { TSchema, SchemaOptions } from '../schema/index' import { Intersect, type TIntersect } from '../intersect/index' import { Union, type TUnion } from '../union/index' import { type TPromise } from '../promise/index' -import { CloneType } from '../clone/type' +import { CreateType } from '../create/type' // ------------------------------------------------------------------ // TypeGuard @@ -96,6 +96,6 @@ export type TAwaited = T extends TPromise ? TAwaited : T /** `[JavaScript]` Constructs a type by recursively unwrapping Promise types */ -export function Awaited(T: T, options: SchemaOptions = {}): TAwaited { - return CloneType(AwaitedResolve(T), options) +export function Awaited(T: T, options?: SchemaOptions): TAwaited { + return CreateType(AwaitedResolve(T), options) as never } diff --git a/src/type/bigint/bigint.ts b/src/type/bigint/bigint.ts index b653a09a2..e98491b2a 100644 --- a/src/type/bigint/bigint.ts +++ b/src/type/bigint/bigint.ts @@ -28,6 +28,7 @@ THE SOFTWARE. import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' +import { CreateType } from '../create/index' export interface BigIntOptions extends SchemaOptions { exclusiveMaximum?: bigint @@ -42,10 +43,6 @@ export interface TBigInt extends TSchema, BigIntOptions { type: 'bigint' } /** `[JavaScript]` Creates a BigInt type */ -export function BigInt(options: BigIntOptions = {}): TBigInt { - return { - ...options, - [Kind]: 'BigInt', - type: 'bigint', - } as never +export function BigInt(options?: BigIntOptions): TBigInt { + return CreateType({ [Kind]: 'BigInt', type: 'bigint' }, options) as never } diff --git a/src/type/boolean/boolean.ts b/src/type/boolean/boolean.ts index 7729a0052..acbf44207 100644 --- a/src/type/boolean/boolean.ts +++ b/src/type/boolean/boolean.ts @@ -28,6 +28,7 @@ THE SOFTWARE. import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' +import { CreateType } from '../create/index' export interface TBoolean extends TSchema { [Kind]: 'Boolean' @@ -35,10 +36,6 @@ export interface TBoolean extends TSchema { type: 'boolean' } /** `[Json]` Creates a Boolean type */ -export function Boolean(options: SchemaOptions = {}): TBoolean { - return { - ...options, - [Kind]: 'Boolean', - type: 'boolean', - } as never +export function Boolean(options?: SchemaOptions): TBoolean { + return CreateType({ [Kind]: 'Boolean', type: 'boolean' }, options) as never } diff --git a/src/type/clone/type.ts b/src/type/clone/type.ts index 89b17b2ee..18a10f3ec 100644 --- a/src/type/clone/type.ts +++ b/src/type/clone/type.ts @@ -26,7 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ -import type { TSchema, SchemaOptions } from '../schema/index' +import { TSchema, SchemaOptions } from '../schema/index' import { Clone } from './value' /** Clones a Rest */ @@ -34,6 +34,6 @@ export function CloneRest(schemas: T): T { return schemas.map((schema) => CloneType(schema)) as never } /** Clones a Type */ -export function CloneType(schema: T, options: SchemaOptions = {}): T { - return { ...Clone(schema), ...options } +export function CloneType(schema: T, options?: SchemaOptions): T { + return options === undefined ? Clone(schema) : Clone({ ...options, ...schema }) } diff --git a/src/type/composite/composite.ts b/src/type/composite/composite.ts index c3a6f8084..26b4406b5 100644 --- a/src/type/composite/composite.ts +++ b/src/type/composite/composite.ts @@ -114,7 +114,7 @@ type TCompositeEvaluate< // prettier-ignore export type TComposite = TCompositeEvaluate // prettier-ignore -export function Composite(T: [...T], options: ObjectOptions = {}): TComposite { +export function Composite(T: [...T], options?: ObjectOptions): TComposite { const K = CompositeKeys(T) const P = CompositeProperties(T, K) const R = Object(P, options) diff --git a/src/type/const/const.ts b/src/type/const/const.ts index 1606b9930..fcaa788a3 100644 --- a/src/type/const/const.ts +++ b/src/type/const/const.ts @@ -44,7 +44,7 @@ import { Readonly, type TReadonly } from '../readonly/index' import { Undefined, type TUndefined } from '../undefined/index' import { Uint8Array, type TUint8Array } from '../uint8array/index' import { Unknown, type TUnknown } from '../unknown/index' -import { CloneType } from '../clone/index' +import { CreateType } from '../create/index' // ------------------------------------------------------------------ // ValueGuard @@ -130,6 +130,6 @@ function FromValue(value: T, root: Root): FromValue = FromValue /** `[JavaScript]` Creates a readonly const type from the given value. */ -export function Const(T: T, options: SchemaOptions = {}): TConst { - return CloneType(FromValue(T, true), options) as never +export function Const(T: T, options?: SchemaOptions): TConst { + return CreateType(FromValue(T, true), options) as never } diff --git a/src/type/constructor-parameters/constructor-parameters.ts b/src/type/constructor-parameters/constructor-parameters.ts index 9b00791ab..3ce3e0034 100644 --- a/src/type/constructor-parameters/constructor-parameters.ts +++ b/src/type/constructor-parameters/constructor-parameters.ts @@ -30,7 +30,6 @@ import type { TSchema, SchemaOptions } from '../schema/index' import type { Ensure } from '../helpers/index' import type { TConstructor } from '../constructor/index' import { Tuple, type TTuple } from '../tuple/index' -import { CloneRest } from '../clone/type' // ------------------------------------------------------------------ // ConstructorParameters @@ -41,6 +40,6 @@ export type TConstructorParameters> = ) /** `[JavaScript]` Extracts the ConstructorParameters from the given Constructor type */ -export function ConstructorParameters>(schema: T, options: SchemaOptions = {}): TConstructorParameters { - return Tuple(CloneRest(schema.parameters), { ...options }) +export function ConstructorParameters>(schema: T, options?: SchemaOptions): TConstructorParameters { + return Tuple(schema.parameters, options) } diff --git a/src/type/constructor/constructor.ts b/src/type/constructor/constructor.ts index 65f440c32..6904b8541 100644 --- a/src/type/constructor/constructor.ts +++ b/src/type/constructor/constructor.ts @@ -32,7 +32,7 @@ import type { Ensure } from '../helpers/index' import type { TReadonlyOptional } from '../readonly-optional/index' import type { TReadonly } from '../readonly/index' import type { TOptional } from '../optional/index' -import { CloneType, CloneRest } from '../clone/type' +import { CreateType } from '../create/type' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ @@ -66,11 +66,5 @@ export interface TConstructor(parameters: [...T], returns: U, options?: SchemaOptions): TConstructor { - return { - ...options, - [Kind]: 'Constructor', - type: 'Constructor', - parameters: CloneRest(parameters), - returns: CloneType(returns), - } as never + return CreateType({ [Kind]: 'Constructor', type: 'Constructor', parameters, returns }, options) as never } diff --git a/src/type/create/immutable.ts b/src/type/create/immutable.ts new file mode 100644 index 000000000..92ff32e5d --- /dev/null +++ b/src/type/create/immutable.ts @@ -0,0 +1,66 @@ +/*-------------------------------------------------------------------------- + +@sinclair/typebox/type + +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 * as ValueGuard from '../guard/value' + +function ImmutableArray(value: unknown[]) { + return globalThis.Object.freeze(value as any).map((value: unknown) => Immutable(value as any)) +} +function ImmutableDate(value: Date) { + return value +} +function ImmutableUint8Array(value: Uint8Array) { + return value +} +function ImmutableRegExp(value: RegExp) { + return value +} +function ImmutableObject(value: Record) { + const result = {} as Record + for (const key of Object.getOwnPropertyNames(value)) { + result[key] = Immutable(value[key]) + } + for (const key of Object.getOwnPropertySymbols(value)) { + result[key] = Immutable(value[key]) + } + return globalThis.Object.freeze(result) +} +/** Specialized deep immutable value. Applies freeze recursively to the given value */ +export function Immutable(value: T): T { + return ValueGuard.IsArray(value) + ? ImmutableArray(value) + : ValueGuard.IsDate(value) + ? ImmutableDate(value) + : ValueGuard.IsUint8Array(value) + ? ImmutableUint8Array(value) + : ValueGuard.IsRegExp(value) + ? ImmutableRegExp(value) + : ValueGuard.IsObject(value) + ? ImmutableObject(value) + : value +} diff --git a/src/type/create/index.ts b/src/type/create/index.ts new file mode 100644 index 000000000..53780a6ef --- /dev/null +++ b/src/type/create/index.ts @@ -0,0 +1,29 @@ +/*-------------------------------------------------------------------------- + +@sinclair/typebox/type + +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. + +---------------------------------------------------------------------------*/ + +export * from './type' diff --git a/src/type/create/type.ts b/src/type/create/type.ts new file mode 100644 index 000000000..4d378a109 --- /dev/null +++ b/src/type/create/type.ts @@ -0,0 +1,45 @@ +/*-------------------------------------------------------------------------- + +@sinclair/typebox/type + +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 { TypeSystemPolicy } from '../../system/policy' +import { SchemaOptions } from '../schema/schema' +import { Immutable } from './immutable' +import { Clone } from '../clone/value' + +/** Creates TypeBox schematics using the configured InstanceMode */ +export function CreateType(schema: Record, options?: SchemaOptions): unknown { + const result = options !== undefined ? Object.assign(options, schema) : schema + switch (TypeSystemPolicy.InstanceMode) { + case 'freeze': + return Immutable(result) + case 'clone': + return Clone(result) + default: + return result + } +} diff --git a/src/type/date/date.ts b/src/type/date/date.ts index 192cea310..44b9d0d3d 100644 --- a/src/type/date/date.ts +++ b/src/type/date/date.ts @@ -28,6 +28,7 @@ THE SOFTWARE. import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' +import { CreateType } from '../create/type' export interface DateOptions extends SchemaOptions { /** The exclusive maximum timestamp value */ @@ -47,10 +48,6 @@ export interface TDate extends TSchema, DateOptions { type: 'date' } /** `[JavaScript]` Creates a Date type */ -export function Date(options: DateOptions = {}): TDate { - return { - ...options, - [Kind]: 'Date', - type: 'Date', - } as never +export function Date(options?: DateOptions): TDate { + return CreateType({ [Kind]: 'Date', type: 'Date' }, options) as never } diff --git a/src/type/discard/discard.ts b/src/type/discard/discard.ts index 9e4b98dc3..cf1688ddd 100644 --- a/src/type/discard/discard.ts +++ b/src/type/discard/discard.ts @@ -30,6 +30,7 @@ function DiscardKey(value: Record, key: PropertyKey) { const { [key]: _, ...rest } = value return rest } +/** Discards property keys from the given value. This function returns a shallow Clone. */ export function Discard(value: Record, keys: PropertyKey[]) { return keys.reduce((acc, key) => DiscardKey(acc, key), value) } diff --git a/src/type/enum/enum.ts b/src/type/enum/enum.ts index 08a87b495..1cd8a5867 100644 --- a/src/type/enum/enum.ts +++ b/src/type/enum/enum.ts @@ -47,7 +47,7 @@ export interface TEnum = Record[] } /** `[Json]` Creates a Enum type */ -export function Enum>(item: T, options: SchemaOptions = {}): TEnum { +export function Enum>(item: T, options?: SchemaOptions): TEnum { if (IsUndefined(item)) throw new Error('Enum undefined or empty') const values1 = globalThis.Object.getOwnPropertyNames(item) .filter((key) => isNaN(key as any)) diff --git a/src/type/exclude/exclude.ts b/src/type/exclude/exclude.ts index 3140a5e10..daee3ea1f 100644 --- a/src/type/exclude/exclude.ts +++ b/src/type/exclude/exclude.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { UnionToTuple, AssertRest, AssertType } from '../helpers/index' import type { TMappedResult } from '../mapped/index' @@ -35,7 +36,6 @@ import { Never, type TNever } from '../never/index' import { type Static } from '../static/index' import { type TUnionEvaluated } from '../union/index' import { ExtendsCheck, ExtendsResult } from '../extends/index' -import { CloneType } from '../clone/type' import { ExcludeFromMappedResult, type TExcludeFromMappedResult } from './exclude-from-mapped-result' import { ExcludeFromTemplateLiteral, type TExcludeFromTemplateLiteral } from './exclude-from-template-literal' @@ -72,10 +72,10 @@ export function Exclude(unionType: L, excl /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ export function Exclude(L: TSchema, R: TSchema, options: SchemaOptions = {}): any { // overloads - if (IsTemplateLiteral(L)) return CloneType(ExcludeFromTemplateLiteral(L, R), options) - if (IsMappedResult(L)) return CloneType(ExcludeFromMappedResult(L, R), options) + if (IsTemplateLiteral(L)) return CreateType(ExcludeFromTemplateLiteral(L, R), options) + if (IsMappedResult(L)) return CreateType(ExcludeFromMappedResult(L, R), options) // prettier-ignore - return CloneType( + return CreateType( IsUnion(L) ? ExcludeRest(L.anyOf, R) : ExtendsCheck(L, R) !== ExtendsResult.False ? Never() : L , options) diff --git a/src/type/extends/extends-from-mapped-key.ts b/src/type/extends/extends-from-mapped-key.ts index ce43b6b60..506ebc854 100644 --- a/src/type/extends/extends-from-mapped-key.ts +++ b/src/type/extends/extends-from-mapped-key.ts @@ -32,6 +32,7 @@ import type { Assert } from '../helpers/index' import { MappedResult, type TMappedResult, type TMappedKey } from '../mapped/index' import { Literal, type TLiteral, type TLiteralValue } from '../literal/index' import { Extends, type TExtends } from './extends' +import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromPropertyKey @@ -51,9 +52,9 @@ function FromPropertyKey< U extends TSchema, L extends TSchema, R extends TSchema ->(K: K, U: U, L: L, R: R, options: SchemaOptions): TFromPropertyKey { +>(K: K, U: U, L: L, R: R, options?: SchemaOptions): TFromPropertyKey { return { - [K]: Extends(Literal(K as TLiteralValue), U, L, R, options) as any + [K]: Extends(Literal(K as TLiteralValue), U, L, R, Clone(options)) as any } as never } // ------------------------------------------------------------------ @@ -77,7 +78,7 @@ function FromPropertyKeys< U extends TSchema, L extends TSchema, R extends TSchema ->(K: [...K], U: U, L: L, R: R, options: SchemaOptions): TFromPropertyKeys { +>(K: [...K], U: U, L: L, R: R, options?: SchemaOptions): TFromPropertyKeys { return K.reduce((Acc, LK) => { return { ...Acc, ...FromPropertyKey(LK, U, L, R, options) } }, {} as TProperties) as never @@ -100,7 +101,7 @@ function FromMappedKey< U extends TSchema, L extends TSchema, R extends TSchema ->(K: K, U: U, L: L, R: R, options: SchemaOptions): TFromMappedKey { +>(K: K, U: U, L: L, R: R, options?: SchemaOptions): TFromMappedKey { return FromPropertyKeys(K.keys, U, L, R, options) as never } // ------------------------------------------------------------------ @@ -123,7 +124,7 @@ export function ExtendsFromMappedKey< L extends TSchema, R extends TSchema, P extends TProperties = TFromMappedKey ->(T: T, U: U, L: L, R: R, options: SchemaOptions): TMappedResult

{ +>(T: T, U: U, L: L, R: R, options?: SchemaOptions): TMappedResult

{ const P = FromMappedKey(T, U, L, R, options) return MappedResult(P) as never } diff --git a/src/type/extends/extends-from-mapped-result.ts b/src/type/extends/extends-from-mapped-result.ts index 2c857cf9d..02a1dc84b 100644 --- a/src/type/extends/extends-from-mapped-result.ts +++ b/src/type/extends/extends-from-mapped-result.ts @@ -30,6 +30,7 @@ import type { TSchema, SchemaOptions } from '../schema/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Extends, type TExtends } from './extends' +import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromProperties @@ -49,9 +50,9 @@ function FromProperties< Right extends TSchema, True extends TSchema, False extends TSchema ->(P: P, Right: Right, True: True, False: False, options: SchemaOptions): TFromProperties { +>(P: P, Right: Right, True: True, False: False, options?: SchemaOptions): TFromProperties { const Acc = {} as TProperties - for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Extends(P[K2], Right, True, False, options) + for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Extends(P[K2], Right, True, False, Clone(options)) return Acc as never } // ------------------------------------------------------------------ @@ -72,7 +73,7 @@ function FromMappedResult< Right extends TSchema, True extends TSchema, False extends TSchema ->(Left: Left, Right: Right, True: True, False: False, options: SchemaOptions): TFromMappedResult { +>(Left: Left, Right: Right, True: True, False: False, options?: SchemaOptions): TFromMappedResult { return FromProperties(Left.properties, Right, True, False, options) as never } // ------------------------------------------------------------------ @@ -95,7 +96,7 @@ export function ExtendsFromMappedResult< True extends TSchema, False extends TSchema, P extends TProperties = TFromMappedResult ->(Left: Left, Right: Right, True: True, False: False, options: SchemaOptions): TMappedResult

{ +>(Left: Left, Right: Right, True: True, False: False, options?: SchemaOptions): TMappedResult

{ const P = FromMappedResult(Left, Right, True, False, options) return MappedResult(P) as never } diff --git a/src/type/extends/extends.ts b/src/type/extends/extends.ts index 614722a4f..9048d1eab 100644 --- a/src/type/extends/extends.ts +++ b/src/type/extends/extends.ts @@ -26,13 +26,13 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import { type TUnion, Union } from '../union/index' import { TMappedKey, TMappedResult } from '../mapped/index' import { ExtendsCheck, ExtendsResult } from './extends-check' import { UnionToTuple } from '../helpers/index' -import { CloneType } from '../clone/type' import { ExtendsFromMappedKey, type TExtendsFromMappedKey } from './extends-from-mapped-key' import { ExtendsFromMappedResult, type TExtendsFromMappedResult } from './extends-from-mapped-result' @@ -70,11 +70,11 @@ export function Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtends /** `[Json]` Creates a Conditional type */ -export function Extends(L: L, R: R, T: T, F: F, options: SchemaOptions = {}) { +export function Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions) { // prettier-ignore return ( IsMappedResult(L) ? ExtendsFromMappedResult(L, R, T, F, options) : - IsMappedKey(L) ? CloneType(ExtendsFromMappedKey(L, R, T, F, options)) : - CloneType(ExtendsResolve(L, R, T, F), options) + IsMappedKey(L) ? CreateType(ExtendsFromMappedKey(L, R, T, F, options)) : + CreateType(ExtendsResolve(L, R, T, F), options) ) as never } diff --git a/src/type/extract/extract.ts b/src/type/extract/extract.ts index 91c8ca5e2..8c94045b2 100644 --- a/src/type/extract/extract.ts +++ b/src/type/extract/extract.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { AssertRest, AssertType, UnionToTuple } from '../helpers/index' import type { TMappedResult } from '../mapped/index' @@ -35,7 +36,6 @@ import { Never, type TNever } from '../never/index' import { type TUnionEvaluated } from '../union/index' import { type TTemplateLiteral } from '../template-literal/index' import { ExtendsCheck, ExtendsResult } from '../extends/index' -import { CloneType } from '../clone/type' import { ExtractFromMappedResult, type TExtractFromMappedResult } from './extract-from-mapped-result' import { ExtractFromTemplateLiteral, type TExtractFromTemplateLiteral } from './extract-from-template-literal' @@ -50,7 +50,7 @@ import { IsMappedResult, IsTemplateLiteral, IsUnion } from '../guard/kind' // prettier-ignore type TExtractRest = AssertRest> extends Static ? L[K] : never -}[number]>> extends infer R extends TSchema[] ? TUnionEvaluated : never + }[number]>> extends infer R extends TSchema[] ? TUnionEvaluated : never function ExtractRest(L: [...L], R: R) { const extracted = L.filter((inner) => ExtendsCheck(inner, R) !== ExtendsResult.False) @@ -71,13 +71,13 @@ export function Extract(type: L, /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ export function Extract(type: L, union: R, options?: SchemaOptions): TExtract /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ -export function Extract(L: TSchema, R: TSchema, options: SchemaOptions = {}): any { +export function Extract(L: TSchema, R: TSchema, options?: SchemaOptions): never { // overloads - if (IsTemplateLiteral(L)) return CloneType(ExtractFromTemplateLiteral(L, R), options) - if (IsMappedResult(L)) return CloneType(ExtractFromMappedResult(L, R), options) + if (IsTemplateLiteral(L)) return CreateType(ExtractFromTemplateLiteral(L, R), options) as never + if (IsMappedResult(L)) return CreateType(ExtractFromMappedResult(L, R), options) as never // prettier-ignore - return CloneType( + return CreateType( IsUnion(L) ? ExtractRest(L.anyOf, R) : - ExtendsCheck(L, R) !== ExtendsResult.False ? L : Never() - , options) + ExtendsCheck(L, R) !== ExtendsResult.False ? L : Never() + , options) as never } diff --git a/src/type/function/function.ts b/src/type/function/function.ts index f4333585c..150fc7338 100644 --- a/src/type/function/function.ts +++ b/src/type/function/function.ts @@ -26,13 +26,13 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import type { Ensure } from '../helpers/index' import type { TReadonlyOptional } from '../readonly-optional/index' import type { TReadonly } from '../readonly/index' import type { TOptional } from '../optional/index' -import { CloneType, CloneRest } from '../clone/type' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ @@ -67,11 +67,5 @@ export interface TFunction(parameters: [...T], returns: U, options?: SchemaOptions): TFunction { - return { - ...options, - [Kind]: 'Function', - type: 'Function', - parameters: CloneRest(parameters), - returns: CloneType(returns), - } as never + return CreateType({ [Kind]: 'Function', type: 'Function', parameters, returns }, options) as never } diff --git a/src/type/guard/value.ts b/src/type/guard/value.ts index c3ecc85fe..e0f63974a 100644 --- a/src/type/guard/value.ts +++ b/src/type/guard/value.ts @@ -26,6 +26,9 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +// -------------------------------------------------------------------------- +// Object Instances +// -------------------------------------------------------------------------- /** Returns true if this value is an async iterator */ export function IsAsyncIterator(value: unknown): value is AsyncIterableIterator { return IsObject(value) && !IsArray(value) && !IsUint8Array(value) && Symbol.asyncIterator in value diff --git a/src/type/indexed/indexed-from-mapped-key.ts b/src/type/indexed/indexed-from-mapped-key.ts index e82b1b5f5..4251cea89 100644 --- a/src/type/indexed/indexed-from-mapped-key.ts +++ b/src/type/indexed/indexed-from-mapped-key.ts @@ -31,6 +31,7 @@ import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { Index, type TIndex } from './indexed' import { MappedResult, type TMappedResult, type TMappedKey } from '../mapped/index' +import { Clone } from '../clone/value' // ------------------------------------------------------------------ // MappedIndexPropertyKey @@ -46,8 +47,8 @@ type TMappedIndexPropertyKey< function MappedIndexPropertyKey< T extends TSchema, K extends PropertyKey ->(T: T, K: K, options: SchemaOptions): TMappedIndexPropertyKey { - return { [K]: Index(T, [K], options) } as never +>(T: T, K: K, options?: SchemaOptions): TMappedIndexPropertyKey { + return { [K]: Index(T, [K], Clone(options)) } as never } // ------------------------------------------------------------------ // MappedIndexPropertyKeys @@ -62,7 +63,7 @@ type TMappedIndexPropertyKeys(T: T, K: [...K], options: SchemaOptions): TMappedIndexPropertyKeys { +>(T: T, K: [...K], options?: SchemaOptions): TMappedIndexPropertyKeys { return K.reduce((Acc, L) => { return { ...Acc, ...MappedIndexPropertyKey(T, L, options) } }, {} as TProperties) as never @@ -78,7 +79,7 @@ type TMappedIndexProperties = Evaluate< function MappedIndexProperties< T extends TSchema, K extends TMappedKey ->(T: T, K: K, options: SchemaOptions): TMappedIndexProperties { +>(T: T, K: K, options?: SchemaOptions): TMappedIndexProperties { return MappedIndexPropertyKeys(T, K.keys, options) as never } // ------------------------------------------------------------------ @@ -97,7 +98,7 @@ export function IndexFromMappedKey< T extends TSchema, K extends TMappedKey, P extends TProperties = TMappedIndexProperties ->(T: T, K: K, options: SchemaOptions): TMappedResult

{ +>(T: T, K: K, options?: SchemaOptions): TMappedResult

{ const P = MappedIndexProperties(T, K, options) return MappedResult(P) as never } diff --git a/src/type/indexed/indexed-from-mapped-result.ts b/src/type/indexed/indexed-from-mapped-result.ts index f51837c1f..d23fa750d 100644 --- a/src/type/indexed/indexed-from-mapped-result.ts +++ b/src/type/indexed/indexed-from-mapped-result.ts @@ -46,7 +46,7 @@ type TFromProperties< function FromProperties< T extends TSchema, P extends TProperties ->(T: T, P: P, options: SchemaOptions): TFromProperties { +>(T: T, P: P, options?: SchemaOptions): TFromProperties { const Acc = {} as Record for(const K2 of Object.getOwnPropertyNames(P)) { Acc[K2] = Index(T, IndexPropertyKeys(P[K2]), options) @@ -67,7 +67,7 @@ type TFromMappedResult< function FromMappedResult< T extends TSchema, R extends TMappedResult ->(T: T, R: R, options: SchemaOptions): TFromMappedResult { +>(T: T, R: R, options?: SchemaOptions): TFromMappedResult { return FromProperties(T, R.properties, options) as never } // ------------------------------------------------------------------ @@ -86,7 +86,7 @@ export function IndexFromMappedResult< T extends TSchema, R extends TMappedResult, P extends TProperties = TFromMappedResult ->(T: T, R: R, options: SchemaOptions): TMappedResult

{ +>(T: T, R: R, options?: SchemaOptions): TMappedResult

{ const P = FromMappedResult(T, R, options) return MappedResult(P) as never } diff --git a/src/type/indexed/indexed.ts b/src/type/indexed/indexed.ts index f5519e46b..6de947666 100644 --- a/src/type/indexed/indexed.ts +++ b/src/type/indexed/indexed.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import { type TSchema, SchemaOptions } from '../schema/index' import { type TObject, type TProperties } from '../object/index' import { type Assert } from '../helpers/index' @@ -38,7 +39,6 @@ import { type TTuple } from '../tuple/index' import { type TArray } from '../array/index' import { IntersectEvaluated, type TIntersectEvaluated } from '../intersect/index' import { UnionEvaluated, type TUnionEvaluated } from '../union/index' -import { CloneType } from '../clone/type' import { IndexPropertyKeys, type TIndexPropertyKeys } from './indexed-property-keys' import { IndexFromMappedKey, type TIndexFromMappedKey } from './indexed-from-mapped-key' @@ -259,12 +259,14 @@ export function Index(T: T, K: readonly [...K], options?: SchemaOptions): TIndex /** `[Json]` Returns an Indexed property type for the given keys */ -export function Index(T: TSchema, K: any, options: SchemaOptions = {}): any { +export function Index(T: TSchema, K: any, options?: SchemaOptions): any { + // mapped-types + if (IsMappedResult(K)) return IndexFromMappedResult(T, K, options) + if (IsMappedKey(K)) return IndexFromMappedKey(T, K, options) // prettier-ignore - return ( - IsMappedResult(K) ? CloneType(IndexFromMappedResult(T, K, options)) : - IsMappedKey(K) ? CloneType(IndexFromMappedKey(T, K, options)) : - IsSchema(K) ? CloneType(FromSchema(T, IndexPropertyKeys(K)), options) : - CloneType(FromSchema(T, K as string[]), options) - ) + return CreateType( + IsSchema(K) + ? FromSchema(T, IndexPropertyKeys(K)) + : FromSchema(T, K as string[]) + , options) as never } diff --git a/src/type/instance-type/instance-type.ts b/src/type/instance-type/instance-type.ts index 358ff7040..853c8da61 100644 --- a/src/type/instance-type/instance-type.ts +++ b/src/type/instance-type/instance-type.ts @@ -26,13 +26,13 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { TConstructor } from '../constructor/index' -import { CloneType } from '../clone/type' export type TInstanceType> = T['returns'] /** `[JavaScript]` Extracts the InstanceType from the given Constructor type */ -export function InstanceType>(schema: T, options: SchemaOptions = {}): TInstanceType { - return CloneType(schema.returns, options) +export function InstanceType>(schema: T, options?: SchemaOptions): TInstanceType { + return CreateType(schema.returns, options) } diff --git a/src/type/integer/integer.ts b/src/type/integer/integer.ts index 3146c25cf..8b15618d3 100644 --- a/src/type/integer/integer.ts +++ b/src/type/integer/integer.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -42,10 +43,6 @@ export interface TInteger extends TSchema, IntegerOptions { type: 'integer' } /** `[Json]` Creates an Integer type */ -export function Integer(options: IntegerOptions = {}): TInteger { - return { - ...options, - [Kind]: 'Integer', - type: 'integer', - } as never +export function Integer(options?: IntegerOptions): TInteger { + return CreateType({ [Kind]: 'Integer', type: 'integer' }, options) as never } diff --git a/src/type/intersect/intersect-create.ts b/src/type/intersect/intersect-create.ts index 300291aa1..6b38ce830 100644 --- a/src/type/intersect/intersect-create.ts +++ b/src/type/intersect/intersect-create.ts @@ -26,9 +26,9 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import { Kind } from '../symbols/index' -import { CloneType, CloneRest } from '../clone/type' import type { TIntersect, IntersectOptions } from './intersect-type' // ------------------------------------------------------------------ @@ -39,14 +39,14 @@ import { IsObject, IsSchema } from '../guard/kind' // IntersectCreate // ------------------------------------------------------------------ // prettier-ignore -export function IntersectCreate(T: [...T], options: IntersectOptions): TIntersect { +export function IntersectCreate(T: [...T], options: IntersectOptions = {}): TIntersect { const allObjects = T.every((schema) => IsObject(schema)) const clonedUnevaluatedProperties = IsSchema(options.unevaluatedProperties) - ? { unevaluatedProperties: CloneType(options.unevaluatedProperties) } + ? { unevaluatedProperties: options.unevaluatedProperties } : {} - return ( + return CreateType( (options.unevaluatedProperties === false || IsSchema(options.unevaluatedProperties) || allObjects - ? { ...options, ...clonedUnevaluatedProperties, [Kind]: 'Intersect', type: 'object', allOf: CloneRest(T) } - : { ...options, ...clonedUnevaluatedProperties, [Kind]: 'Intersect', allOf: CloneRest(T) }) - ) as never + ? { ...clonedUnevaluatedProperties, [Kind]: 'Intersect', type: 'object', allOf: T } + : { ...clonedUnevaluatedProperties, [Kind]: 'Intersect', allOf: T }) + , options) as never } diff --git a/src/type/intersect/intersect-evaluated.ts b/src/type/intersect/intersect-evaluated.ts index f8a5c884e..a0c73484b 100644 --- a/src/type/intersect/intersect-evaluated.ts +++ b/src/type/intersect/intersect-evaluated.ts @@ -28,9 +28,8 @@ THE SOFTWARE. import type { SchemaOptions, TSchema } from '../schema/index' import { OptionalKind } from '../symbols/index' -import { CloneType } from '../clone/type' +import { CreateType } from '../create/type' import { Discard } from '../discard/index' - import { Never, type TNever } from '../never/index' import { Optional, type TOptional } from '../optional/index' import type { TReadonly } from '../readonly/index' @@ -116,8 +115,8 @@ export type TIntersectEvaluated = ( ) /** `[Json]` Creates an evaluated Intersect type */ export function IntersectEvaluated>(T: [...T], options: IntersectOptions = {}): R { - if (T.length === 0) return Never(options) as R - if (T.length === 1) return CloneType(T[0], options) as R + if (T.length === 0) return Never(options) as never + if (T.length === 1) return CreateType(T[0], options) as never if (T.some((schema) => IsTransform(schema))) throw new Error('Cannot intersect transform types') - return ResolveIntersect(T, options) as R + return ResolveIntersect(T, options) as never } diff --git a/src/type/intersect/intersect.ts b/src/type/intersect/intersect.ts index 5672f4c63..66275057f 100644 --- a/src/type/intersect/intersect.ts +++ b/src/type/intersect/intersect.ts @@ -26,10 +26,9 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema } from '../schema/index' -import { CloneType } from '../clone/type' import { Never, type TNever } from '../never/index' - import { TIntersect, IntersectOptions } from './intersect-type' import { IntersectCreate } from './intersect-create' @@ -47,9 +46,9 @@ export type Intersect = ( TIntersect ) /** `[Json]` Creates an evaluated Intersect type */ -export function Intersect(T: [...T], options: IntersectOptions = {}): Intersect { - if (T.length === 0) return Never(options) as Intersect - if (T.length === 1) return CloneType(T[0], options) as Intersect +export function Intersect(T: [...T], options?: IntersectOptions): Intersect { + if (T.length === 0) return Never(options) as never + if (T.length === 1) return CreateType(T[0], options) as never if (T.some((schema) => IsTransform(schema))) throw new Error('Cannot intersect transform types') - return IntersectCreate(T, options) as Intersect + return IntersectCreate(T, options) as never } diff --git a/src/type/intrinsic/intrinsic-from-mapped-key.ts b/src/type/intrinsic/intrinsic-from-mapped-key.ts index 51ce4c719..16afb241e 100644 --- a/src/type/intrinsic/intrinsic-from-mapped-key.ts +++ b/src/type/intrinsic/intrinsic-from-mapped-key.ts @@ -32,6 +32,7 @@ import { Assert } from '../helpers/index' import { MappedResult, type TMappedResult, type TMappedKey } from '../mapped/index' import { Intrinsic, type TIntrinsic, type IntrinsicMode } from './intrinsic' import { Literal, type TLiteral, type TLiteralValue } from '../literal/index' +import { Clone } from '../clone/value' // ------------------------------------------------------------------ // MappedIntrinsicPropertyKey @@ -49,7 +50,7 @@ function MappedIntrinsicPropertyKey< M extends IntrinsicMode, >(K: K, M: M, options: SchemaOptions): TMappedIntrinsicPropertyKey { return { - [K]: Intrinsic(Literal(K as TLiteralValue), M, options) + [K]: Intrinsic(Literal(K as TLiteralValue), M, Clone(options)) } as never } // ------------------------------------------------------------------ @@ -70,9 +71,11 @@ function MappedIntrinsicPropertyKeys< K extends PropertyKey[], M extends IntrinsicMode >(K: [...K], M: M, options: SchemaOptions): TMappedIntrinsicPropertyKeys { - return K.reduce((Acc, L) => { + const result = K.reduce((Acc, L) => { return { ...Acc, ...MappedIntrinsicPropertyKey(L, M, options) } }, {} as TProperties) as never + + return result } // ------------------------------------------------------------------ // MappedIntrinsicProperties diff --git a/src/type/intrinsic/intrinsic.ts b/src/type/intrinsic/intrinsic.ts index 2f7e23c6c..6745597ec 100644 --- a/src/type/intrinsic/intrinsic.ts +++ b/src/type/intrinsic/intrinsic.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { TemplateLiteral, TemplateLiteralParseExact, IsTemplateLiteralExpressionFinite, TemplateLiteralExpressionGenerate, type TTemplateLiteral, type TTemplateLiteralKind } from '../template-literal/index' import { IntrinsicFromMappedKey, type TIntrinsicFromMappedKey } from './intrinsic-from-mapped-key' @@ -134,7 +135,7 @@ export function Intrinsic(schema: /** Applies an intrinsic string manipulation to the given type. */ export function Intrinsic(schema: T, mode: M, options?: SchemaOptions): TIntrinsic /** Applies an intrinsic string manipulation to the given type. */ -export function Intrinsic(schema: TSchema, mode: IntrinsicMode, options: SchemaOptions = {}): any { +export function Intrinsic(schema: TSchema, mode: IntrinsicMode, options: SchemaOptions = {}): never { // prettier-ignore return ( // Intrinsic-Mapped-Inference @@ -143,6 +144,7 @@ export function Intrinsic(schema: TSchema, mode: IntrinsicMode, options: SchemaO IsTemplateLiteral(schema) ? FromTemplateLiteral(schema, mode, schema) : IsUnion(schema) ? Union(FromRest(schema.anyOf, mode), options) : IsLiteral(schema) ? Literal(FromLiteralValue(schema.const, mode), options) : - schema - ) + // Default Type + CreateType(schema, options) + ) as never } diff --git a/src/type/iterator/iterator.ts b/src/type/iterator/iterator.ts index 335bae40c..da528a8ae 100644 --- a/src/type/iterator/iterator.ts +++ b/src/type/iterator/iterator.ts @@ -26,9 +26,9 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' -import { CloneType } from '../clone/type' import { Kind } from '../symbols/index' export interface TIterator extends TSchema { @@ -38,11 +38,6 @@ export interface TIterator extends TSchema { items: T } /** `[JavaScript]` Creates an Iterator type */ -export function Iterator(items: T, options: SchemaOptions = {}): TIterator { - return { - ...options, - [Kind]: 'Iterator', - type: 'Iterator', - items: CloneType(items), - } as never +export function Iterator(items: T, options?: SchemaOptions): TIterator { + return CreateType({ [Kind]: 'Iterator', type: 'Iterator', items }, options) as never } diff --git a/src/type/keyof/keyof-from-mapped-result.ts b/src/type/keyof/keyof-from-mapped-result.ts index 1f4f7df33..9991b7c15 100644 --- a/src/type/keyof/keyof-from-mapped-result.ts +++ b/src/type/keyof/keyof-from-mapped-result.ts @@ -31,7 +31,7 @@ import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { KeyOf, type TKeyOf } from './keyof' - +import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromProperties // ------------------------------------------------------------------ @@ -44,9 +44,9 @@ type TFromProperties< // prettier-ignore function FromProperties< K extends TProperties ->(K: K, options: SchemaOptions): TFromProperties { +>(K: K, options?: SchemaOptions): TFromProperties { const Acc = {} as TProperties - for(const K2 of globalThis.Object.getOwnPropertyNames(K)) Acc[K2] = KeyOf(K[K2], options) + for(const K2 of globalThis.Object.getOwnPropertyNames(K)) Acc[K2] = KeyOf(K[K2], Clone(options)) return Acc as never } // ------------------------------------------------------------------ @@ -61,7 +61,7 @@ type TFromMappedResult< // prettier-ignore function FromMappedResult< R extends TMappedResult ->(R: R, options: SchemaOptions): TFromMappedResult { +>(R: R, options?: SchemaOptions): TFromMappedResult { return FromProperties(R.properties, options) as never } // ------------------------------------------------------------------ @@ -78,7 +78,7 @@ export type TKeyOfFromMappedResult< export function KeyOfFromMappedResult< R extends TMappedResult, P extends TProperties = TFromMappedResult ->(R: R, options: SchemaOptions): TMappedResult

{ +>(R: R, options?: SchemaOptions): TMappedResult

{ const P = FromMappedResult(R, options) return MappedResult(P) as never } diff --git a/src/type/keyof/keyof.ts b/src/type/keyof/keyof.ts index 895eaa6e0..2e4c42df6 100644 --- a/src/type/keyof/keyof.ts +++ b/src/type/keyof/keyof.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import type { Assert, Ensure } from '../helpers/index' import type { TMappedResult } from '../mapped/index' @@ -34,7 +35,6 @@ import { Literal, type TLiteral, type TLiteralValue } from '../literal/index' import { Number, type TNumber } from '../number/index' import { KeyOfPropertyKeys, type TKeyOfPropertyKeys } from './keyof-property-keys' import { UnionEvaluated, type TUnionEvaluated } from '../union/index' -import { CloneType } from '../clone/type' import { KeyOfFromMappedResult, type TKeyOfFromMappedResult } from './keyof-from-mapped-result' // ------------------------------------------------------------------ @@ -73,13 +73,13 @@ export function KeyOf(T: T, options?: SchemaOptions): T /** `[Json]` Creates a KeyOf type */ export function KeyOf(T: T, options?: SchemaOptions): TKeyOf /** `[Json]` Creates a KeyOf type */ -export function KeyOf(T: TSchema, options: SchemaOptions = {}): any { +export function KeyOf(T: TSchema, options?: SchemaOptions): never { if (IsMappedResult(T)) { - return KeyOfFromMappedResult(T, options) + return KeyOfFromMappedResult(T, options) as never } else { const K = KeyOfPropertyKeys(T) const S = KeyOfPropertyKeysToRest(K) const U = UnionEvaluated(S) - return CloneType(U, options) + return CreateType(U, options) as never } } diff --git a/src/type/literal/literal.ts b/src/type/literal/literal.ts index 3091b4dbd..5a17d8959 100644 --- a/src/type/literal/literal.ts +++ b/src/type/literal/literal.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -43,11 +44,13 @@ export interface TLiteral extends TSche const: T } /** `[Json]` Creates a Literal type */ -export function Literal(value: T, options: SchemaOptions = {}): TLiteral { - return { - ...options, - [Kind]: 'Literal', - const: value, - type: typeof value as 'string' | 'number' | 'boolean', - } as never +export function Literal(value: T, options?: SchemaOptions): TLiteral { + return CreateType( + { + [Kind]: 'Literal', + const: value, + type: typeof value as 'string' | 'number' | 'boolean', + }, + options, + ) as never } diff --git a/src/type/mapped/mapped-key.ts b/src/type/mapped/mapped-key.ts index c3a6f288c..42a9a6926 100644 --- a/src/type/mapped/mapped-key.ts +++ b/src/type/mapped/mapped-key.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import { Kind } from '../symbols/index' @@ -36,8 +37,8 @@ export interface TMappedKey extends TSc } // prettier-ignore export function MappedKey(T: [...T]): TMappedKey { - return { + return CreateType({ [Kind]: 'MappedKey', keys: T - } as never + }) as never } diff --git a/src/type/mapped/mapped-result.ts b/src/type/mapped/mapped-result.ts index d2aade75c..7faf21d75 100644 --- a/src/type/mapped/mapped-result.ts +++ b/src/type/mapped/mapped-result.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import type { TProperties } from '../object/index' import { Kind } from '../symbols/index' @@ -37,8 +38,8 @@ export interface TMappedResult extends TSch } // prettier-ignore export function MappedResult(properties: T): TMappedResult { - return { + return CreateType({ [Kind]: 'MappedResult', properties - } as never + }) as never } diff --git a/src/type/mapped/mapped.ts b/src/type/mapped/mapped.ts index 797679b9c..30301a808 100644 --- a/src/type/mapped/mapped.ts +++ b/src/type/mapped/mapped.ts @@ -29,7 +29,7 @@ THE SOFTWARE. import type { TSchema } from '../schema/index' import type { Ensure, Evaluate, Assert } from '../helpers/index' import { Kind, OptionalKind, ReadonlyKind } from '../symbols/index' -import { CloneType } from '../clone/type' +import { CreateType } from '../create/type' import { Discard } from '../discard/index' // evaluation types import { Array, type TArray } from '../array/index' @@ -261,9 +261,9 @@ export function Mapped = TMappedFunction, R extends TMapped = TMapped>(key: [...K], map: F, options?: ObjectOptions): R /** `[Json]` Creates a Mapped object type */ -export function Mapped(key: any, map: Function, options: ObjectOptions = {}) { +export function Mapped(key: any, map: Function, options?: ObjectOptions) { const K = IsSchema(key) ? IndexPropertyKeys(key) : (key as PropertyKey[]) const RT = map({ [Kind]: 'MappedKey', keys: K } as TMappedKey) const R = MappedFunctionReturnType(K, RT) - return CloneType(Object(R), options) + return Object(R, options) } diff --git a/src/type/never/never.ts b/src/type/never/never.ts index d1ff1c234..f2df6451e 100644 --- a/src/type/never/never.ts +++ b/src/type/never/never.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -35,10 +36,6 @@ export interface TNever extends TSchema { not: {} } /** `[Json]` Creates a Never type */ -export function Never(options: SchemaOptions = {}): TNever { - return { - ...options, - [Kind]: 'Never', - not: {}, - } as never +export function Never(options?: SchemaOptions): TNever { + return CreateType({ [Kind]: 'Never', not: {} }, options) as never } diff --git a/src/type/not/not.ts b/src/type/not/not.ts index 7315fec86..256a3c8eb 100644 --- a/src/type/not/not.ts +++ b/src/type/not/not.ts @@ -26,9 +26,9 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' -import { CloneType } from '../clone/type' import { Kind } from '../symbols/index' export interface TNot extends TSchema { @@ -37,10 +37,6 @@ export interface TNot extends TSchema { not: T } /** `[Json]` Creates a Not type */ -export function Not(schema: T, options?: SchemaOptions): TNot { - return { - ...options, - [Kind]: 'Not', - not: CloneType(schema), - } as never +export function Not(not: T, options?: SchemaOptions): TNot { + return CreateType({ [Kind]: 'Not', not }, options) as never } diff --git a/src/type/null/null.ts b/src/type/null/null.ts index 40690048a..f953d04ec 100644 --- a/src/type/null/null.ts +++ b/src/type/null/null.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -35,10 +36,6 @@ export interface TNull extends TSchema { type: 'null' } /** `[Json]` Creates a Null type */ -export function Null(options: SchemaOptions = {}): TNull { - return { - ...options, - [Kind]: 'Null', - type: 'null', - } as never +export function Null(options?: SchemaOptions): TNull { + return CreateType({ [Kind]: 'Null', type: 'null' }, options) as never } diff --git a/src/type/number/number.ts b/src/type/number/number.ts index db7392cd0..0ef585560 100644 --- a/src/type/number/number.ts +++ b/src/type/number/number.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -42,10 +43,6 @@ export interface TNumber extends TSchema, NumberOptions { type: 'number' } /** `[Json]` Creates a Number type */ -export function Number(options: NumberOptions = {}): TNumber { - return { - ...options, - [Kind]: 'Number', - type: 'number', - } as never +export function Number(options?: NumberOptions): TNumber { + return CreateType({ [Kind]: 'Number', type: 'number' }, options) as never } diff --git a/src/type/object/object.ts b/src/type/object/object.ts index a9d4ce358..18d1559b2 100644 --- a/src/type/object/object.ts +++ b/src/type/object/object.ts @@ -26,12 +26,12 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import type { Evaluate } from '../helpers/index' import type { TReadonly } from '../readonly/index' import type { TOptional } from '../optional/index' -import { CloneType } from '../clone/type' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ @@ -83,19 +83,18 @@ export interface TObject extends TSchema, O properties: T required?: string[] } +function RequiredKeys(properties: T): string[] { + const keys: string[] = [] + for (let key in properties) { + if (!IsOptional(properties[key])) keys.push(key) + } + return keys +} /** `[Json]` Creates an Object type */ -function _Object(properties: T, options: ObjectOptions = {}): TObject { - const propertyKeys = globalThis.Object.getOwnPropertyNames(properties) - const optionalKeys = propertyKeys.filter((key) => IsOptional(properties[key])) - const requiredKeys = propertyKeys.filter((name) => !optionalKeys.includes(name)) - const clonedAdditionalProperties = IsSchema(options.additionalProperties) ? { additionalProperties: CloneType(options.additionalProperties) } : {} - const clonedProperties = {} as Record - for (const key of propertyKeys) clonedProperties[key] = CloneType(properties[key]) - return ( - requiredKeys.length > 0 - ? { ...options, ...clonedAdditionalProperties, [Kind]: 'Object', type: 'object', properties: clonedProperties, required: requiredKeys } - : { ...options, ...clonedAdditionalProperties, [Kind]: 'Object', type: 'object', properties: clonedProperties } - ) as never +function _Object(properties: T, options?: ObjectOptions): TObject { + const required = RequiredKeys(properties) + const schematic = required.length > 0 ? { [Kind]: 'Object', type: 'object', properties, required } : { [Kind]: 'Object', type: 'object', properties } + return CreateType(schematic, options) as never } /** `[Json]` Creates an Object type */ diff --git a/src/type/omit/omit-from-mapped-key.ts b/src/type/omit/omit-from-mapped-key.ts index 3ca1822dc..5eeb68660 100644 --- a/src/type/omit/omit-from-mapped-key.ts +++ b/src/type/omit/omit-from-mapped-key.ts @@ -30,6 +30,7 @@ import type { TSchema, SchemaOptions } from '../schema/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult, type TMappedKey } from '../mapped/index' import { Omit, type TOmit } from './omit' +import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromPropertyKey @@ -45,9 +46,9 @@ type TFromPropertyKey< function FromPropertyKey< T extends TSchema, K extends PropertyKey, ->(T: T, K: K, options: SchemaOptions): TFromPropertyKey { +>(T: T, K: K, options?: SchemaOptions): TFromPropertyKey { return { - [K]: Omit(T, [K], options) + [K]: Omit(T, [K], Clone(options)) } as never } // ------------------------------------------------------------------ @@ -67,7 +68,7 @@ type TFromPropertyKeys< function FromPropertyKeys< T extends TSchema, K extends PropertyKey[] ->(T: T, K: [...K], options: SchemaOptions): TFromPropertyKeys { +>(T: T, K: [...K], options?: SchemaOptions): TFromPropertyKeys { return K.reduce((Acc, LK) => { return { ...Acc, ...FromPropertyKey(T, LK, options) } }, {} as TProperties) as never @@ -86,7 +87,7 @@ type TFromMappedKey< function FromMappedKey< T extends TSchema, K extends TMappedKey, ->(T: T, K: K, options: SchemaOptions): TFromMappedKey { +>(T: T, K: K, options?: SchemaOptions): TFromMappedKey { return FromPropertyKeys(T, K.keys, options) as never } // ------------------------------------------------------------------ @@ -105,7 +106,7 @@ export function OmitFromMappedKey< T extends TSchema, K extends TMappedKey, P extends TProperties = TFromMappedKey ->(T: T, K: K, options: SchemaOptions): TMappedResult

{ +>(T: T, K: K, options?: SchemaOptions): TMappedResult

{ const P = FromMappedKey(T, K, options) return MappedResult(P) as never } diff --git a/src/type/omit/omit-from-mapped-result.ts b/src/type/omit/omit-from-mapped-result.ts index 5f54e4802..205047ea8 100644 --- a/src/type/omit/omit-from-mapped-result.ts +++ b/src/type/omit/omit-from-mapped-result.ts @@ -31,6 +31,7 @@ import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Omit, type TOmit } from './omit' +import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromProperties @@ -46,9 +47,9 @@ type TFromProperties< function FromProperties< P extends TProperties, K extends PropertyKey[], ->(P: P, K: [...K], options: SchemaOptions): TFromProperties { +>(P: P, K: [...K], options?: SchemaOptions): TFromProperties { const Acc = {} as TProperties - for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Omit(P[K2], K, options) + for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Omit(P[K2], K, Clone(options)) return Acc as never } // ------------------------------------------------------------------ @@ -65,7 +66,7 @@ type TFromMappedResult< function FromMappedResult< R extends TMappedResult, K extends PropertyKey[] ->(R: R, K: [...K], options: SchemaOptions): TFromMappedResult { +>(R: R, K: [...K], options?: SchemaOptions): TFromMappedResult { return FromProperties(R.properties, K, options) as never } // ------------------------------------------------------------------ @@ -84,7 +85,7 @@ export function OmitFromMappedResult< R extends TMappedResult, K extends PropertyKey[], P extends TProperties = TFromMappedResult ->(R: R, K: [...K], options: SchemaOptions): TMappedResult

{ +>(R: R, K: [...K], options?: SchemaOptions): TMappedResult

{ const P = FromMappedResult(R, K, options) return MappedResult(P) as never } diff --git a/src/type/omit/omit.ts b/src/type/omit/omit.ts index 19751fdc4..0d959fe25 100644 --- a/src/type/omit/omit.ts +++ b/src/type/omit/omit.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { TupleToUnion, Evaluate } from '../helpers/index' import { type TRecursive } from '../recursive/index' @@ -36,7 +37,6 @@ import { Object, type TObject, type TProperties } from '../object/index' import { IndexPropertyKeys, type TIndexPropertyKeys } from '../indexed/index' import { Discard } from '../discard/index' import { TransformKind } from '../symbols/index' -import { CloneType } from '../clone/type' import { OmitFromMappedKey, type TOmitFromMappedKey } from './omit-from-mapped-key' import { OmitFromMappedResult, type TOmitFromMappedResult } from './omit-from-mapped-result' @@ -115,13 +115,13 @@ export function Omit(T: T, K: K, option export function Omit>(T: T, K: K, options?: SchemaOptions): TOmit /** `[Json]` Constructs a type whose keys are omitted from the given type */ export function Omit(T: T, K: readonly [...K], options?: SchemaOptions): TOmit -export function Omit(T: TSchema, K: any, options: SchemaOptions = {}): any { +export function Omit(T: TSchema, K: any, options?: SchemaOptions): any { // mapped if (IsMappedKey(K)) return OmitFromMappedKey(T, K, options) if (IsMappedResult(T)) return OmitFromMappedResult(T, K, options) // non-mapped const I = IsSchema(K) ? IndexPropertyKeys(K) : (K as string[]) const D = Discard(T, [TransformKind, '$id', 'required']) as TSchema - const R = CloneType(OmitResolve(T, I), options) - return { ...D, ...R } + const R = OmitResolve(T, I) + return CreateType({ ...D, ...R }, options) } diff --git a/src/type/optional/optional.ts b/src/type/optional/optional.ts index 0ecd8cad4..a481135b7 100644 --- a/src/type/optional/optional.ts +++ b/src/type/optional/optional.ts @@ -26,10 +26,10 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import type { Ensure } from '../helpers/index' import { OptionalKind } from '../symbols/index' -import { CloneType } from '../clone/type' import { Discard } from '../discard/index' import type { TMappedResult } from '../mapped/index' @@ -40,14 +40,14 @@ import { IsMappedResult } from '../guard/kind' // ------------------------------------------------------------------ type TRemoveOptional = T extends TOptional ? S : T function RemoveOptional(schema: T) { - return Discard(CloneType(schema), [OptionalKind]) + return CreateType(Discard(schema, [OptionalKind])) } // ------------------------------------------------------------------ // AddOptional // ------------------------------------------------------------------ type TAddOptional = T extends TOptional ? TOptional : Ensure> function AddOptional(schema: T) { - return { ...CloneType(schema), [OptionalKind]: 'Optional' } + return CreateType({ ...schema, [OptionalKind]: 'Optional' }) } // prettier-ignore export type TOptionalWithFlag = diff --git a/src/type/parameters/parameters.ts b/src/type/parameters/parameters.ts index 6e5bcbe5d..a7a0daa45 100644 --- a/src/type/parameters/parameters.ts +++ b/src/type/parameters/parameters.ts @@ -30,7 +30,6 @@ import type { TSchema, SchemaOptions } from '../schema/index' import type { TFunction } from '../function/index' import type { Ensure } from '../helpers/index' import { Tuple, type TTuple } from '../tuple/index' -import { CloneRest } from '../clone/type' // ------------------------------------------------------------------ // Parameters @@ -38,6 +37,6 @@ import { CloneRest } from '../clone/type' export type TParameters = Ensure> /** `[JavaScript]` Extracts the Parameters from the given Function type */ -export function Parameters>(schema: T, options: SchemaOptions = {}): TParameters { - return Tuple(CloneRest(schema.parameters), { ...options }) +export function Parameters>(schema: T, options?: SchemaOptions): TParameters { + return Tuple(schema.parameters, options) } diff --git a/src/type/partial/partial-from-mapped-result.ts b/src/type/partial/partial-from-mapped-result.ts index 466c608ff..af60533b8 100644 --- a/src/type/partial/partial-from-mapped-result.ts +++ b/src/type/partial/partial-from-mapped-result.ts @@ -31,6 +31,7 @@ import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Partial, type TPartial } from './partial' +import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromProperties @@ -44,9 +45,9 @@ type TFromProperties< // prettier-ignore function FromProperties< P extends TProperties ->(K: P, options: SchemaOptions): TFromProperties

{ +>(K: P, options?: SchemaOptions): TFromProperties

{ const Acc = {} as TProperties - for(const K2 of globalThis.Object.getOwnPropertyNames(K)) Acc[K2] = Partial(K[K2], options) + for(const K2 of globalThis.Object.getOwnPropertyNames(K)) Acc[K2] = Partial(K[K2], Clone(options)) return Acc as never } // ------------------------------------------------------------------ @@ -61,7 +62,7 @@ type TFromMappedResult< // prettier-ignore function FromMappedResult< R extends TMappedResult ->(R: R, options: SchemaOptions): TFromMappedResult { +>(R: R, options?: SchemaOptions): TFromMappedResult { return FromProperties(R.properties, options) as never } // ------------------------------------------------------------------ @@ -78,7 +79,7 @@ export type TPartialFromMappedResult< export function PartialFromMappedResult< R extends TMappedResult, P extends TProperties = TFromMappedResult ->(R: R, options: SchemaOptions): TMappedResult

{ +>(R: R, options?: SchemaOptions): TMappedResult

{ const P = FromMappedResult(R, options) return MappedResult(P) as never } diff --git a/src/type/partial/partial.ts b/src/type/partial/partial.ts index 27a37b0b7..a2382b281 100644 --- a/src/type/partial/partial.ts +++ b/src/type/partial/partial.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Evaluate } from '../helpers/index' import type { TMappedResult } from '../mapped/index' @@ -38,7 +39,6 @@ import { type TIntersect, Intersect } from '../intersect/index' import { type TUnion, Union } from '../union/index' import { Discard } from '../discard/index' import { TransformKind } from '../symbols/index' -import { CloneType } from '../clone/type' import { PartialFromMappedResult, type TPartialFromMappedResult } from './partial-from-mapped-result' @@ -104,9 +104,9 @@ export function Partial(T: T, options?: SchemaOptions): /** `[Json]` Constructs a type where all properties are optional */ export function Partial(T: T, options?: SchemaOptions): TPartial /** `[Json]` Constructs a type where all properties are optional */ -export function Partial(T: TSchema, options: SchemaOptions = {}): any { +export function Partial(T: TSchema, options?: SchemaOptions): any { if (IsMappedResult(T)) return PartialFromMappedResult(T, options) const D = Discard(T, [TransformKind, '$id', 'required']) as TSchema - const R = CloneType(PartialResolve(T), options) - return { ...D, ...R } as never + const R = PartialResolve(T) + return CreateType({ ...options, ...D, ...R }) as never } diff --git a/src/type/pick/pick-from-mapped-key.ts b/src/type/pick/pick-from-mapped-key.ts index 7bd87f09e..062e1e527 100644 --- a/src/type/pick/pick-from-mapped-key.ts +++ b/src/type/pick/pick-from-mapped-key.ts @@ -30,6 +30,7 @@ import type { TSchema, SchemaOptions } from '../schema/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult, type TMappedKey } from '../mapped/index' import { Pick, type TPick } from './pick' +import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromPropertyKey @@ -45,9 +46,9 @@ type TFromPropertyKey< function FromPropertyKey< T extends TSchema, K extends PropertyKey, ->(T: T, K: K, options: SchemaOptions): TFromPropertyKey { +>(T: T, K: K, options?: SchemaOptions): TFromPropertyKey { return { - [K]: Pick(T, [K], options) + [K]: Pick(T, [K], Clone(options)) } as never } // ------------------------------------------------------------------ @@ -67,7 +68,7 @@ type TFromPropertyKeys< function FromPropertyKeys< T extends TSchema, K extends PropertyKey[] ->(T: T, K: [...K], options: SchemaOptions): TFromPropertyKeys { +>(T: T, K: [...K], options?: SchemaOptions): TFromPropertyKeys { return K.reduce((Acc, LK) => { return { ...Acc, ...FromPropertyKey(T, LK, options) } }, {} as TProperties) as never @@ -86,7 +87,7 @@ type TFromMappedKey< function FromMappedKey< T extends TSchema, K extends TMappedKey, ->(T: T, K: K, options: SchemaOptions): TFromMappedKey { +>(T: T, K: K, options?: SchemaOptions): TFromMappedKey { return FromPropertyKeys(T, K.keys, options) as never } // ------------------------------------------------------------------ @@ -105,7 +106,7 @@ export function PickFromMappedKey< T extends TSchema, K extends TMappedKey, P extends TProperties = TFromMappedKey ->(T: T, K: K, options: SchemaOptions): TMappedResult

{ +>(T: T, K: K, options?: SchemaOptions): TMappedResult

{ const P = FromMappedKey(T, K, options) return MappedResult(P) as never } diff --git a/src/type/pick/pick-from-mapped-result.ts b/src/type/pick/pick-from-mapped-result.ts index 43b006457..3abf5ad17 100644 --- a/src/type/pick/pick-from-mapped-result.ts +++ b/src/type/pick/pick-from-mapped-result.ts @@ -31,6 +31,7 @@ import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Pick, type TPick } from './pick' +import { Clone } from '../clone/value' // ------------------------------------------------------------------ // FromProperties @@ -46,9 +47,9 @@ type TFromProperties< function FromProperties< P extends TProperties, K extends PropertyKey[], ->(P: P, K: [...K], options: SchemaOptions): TFromProperties { +>(P: P, K: [...K], options?: SchemaOptions): TFromProperties { const Acc = {} as TProperties - for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Pick(P[K2], K, options) + for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Pick(P[K2], K, Clone(options)) return Acc as never } // ------------------------------------------------------------------ @@ -65,7 +66,7 @@ type TFromMappedResult< function FromMappedResult< R extends TMappedResult, K extends PropertyKey[] ->(R: R, K: [...K], options: SchemaOptions): TFromMappedResult { +>(R: R, K: [...K], options?: SchemaOptions): TFromMappedResult { return FromProperties(R.properties, K, options) as never } // ------------------------------------------------------------------ @@ -84,7 +85,7 @@ export function PickFromMappedResult< R extends TMappedResult, K extends PropertyKey[], P extends TProperties = TFromMappedResult ->(R: R, K: [...K], options: SchemaOptions): TMappedResult

{ +>(R: R, K: [...K], options?: SchemaOptions): TMappedResult

{ const P = FromMappedResult(R, K, options) return MappedResult(P) as never } diff --git a/src/type/pick/pick.ts b/src/type/pick/pick.ts index 60a7b2227..017914046 100644 --- a/src/type/pick/pick.ts +++ b/src/type/pick/pick.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { TupleToUnion, Evaluate } from '../helpers/index' import { type TRecursive } from '../recursive/index' @@ -36,7 +37,6 @@ import type { TMappedKey, TMappedResult } from '../mapped/index' import { IndexPropertyKeys, type TIndexPropertyKeys } from '../indexed/index' import { Discard } from '../discard/index' import { TransformKind } from '../symbols/index' -import { CloneType } from '../clone/type' import { PickFromMappedKey, type TPickFromMappedKey } from './pick-from-mapped-key' import { PickFromMappedResult, type TPickFromMappedResult } from './pick-from-mapped-result' @@ -106,13 +106,13 @@ export function Pick(T: T, K: K, option export function Pick>(T: T, K: K, options?: SchemaOptions): TPick /** `[Json]` Constructs a type whose keys are picked from the given type */ export function Pick(T: T, K: readonly [...K], options?: SchemaOptions): TPick -export function Pick(T: TSchema, K: any, options: SchemaOptions = {}): any { +export function Pick(T: TSchema, K: any, options?: SchemaOptions): any { // mapped if (IsMappedKey(K)) return PickFromMappedKey(T, K, options) if (IsMappedResult(T)) return PickFromMappedResult(T, K, options) // non-mapped const I = IsSchema(K) ? IndexPropertyKeys(K) : (K as string[]) const D = Discard(T, [TransformKind, '$id', 'required']) as TSchema - const R = CloneType(PickResolve(T, I), options) - return { ...D, ...R } + const R = PickResolve(T, I) + return CreateType({ ...D, ...R }, options) } diff --git a/src/type/promise/promise.ts b/src/type/promise/promise.ts index bd9504194..4a2488408 100644 --- a/src/type/promise/promise.ts +++ b/src/type/promise/promise.ts @@ -26,9 +26,9 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' -import { CloneType } from '../clone/type' import { Kind } from '../symbols/index' export interface TPromise extends TSchema { @@ -38,11 +38,6 @@ export interface TPromise extends TSchema { item: TSchema } /** `[JavaScript]` Creates a Promise type */ -export function Promise(item: T, options: SchemaOptions = {}): TPromise { - return { - ...options, - [Kind]: 'Promise', - type: 'Promise', - item: CloneType(item), - } as never +export function Promise(item: T, options?: SchemaOptions): TPromise { + return CreateType({ [Kind]: 'Promise', type: 'Promise', item }, options) as never } diff --git a/src/type/readonly/readonly.ts b/src/type/readonly/readonly.ts index 546caddb7..47d9ee0da 100644 --- a/src/type/readonly/readonly.ts +++ b/src/type/readonly/readonly.ts @@ -26,10 +26,10 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import type { Ensure } from '../helpers/index' import { ReadonlyKind } from '../symbols/index' -import { CloneType } from '../clone/type' import { Discard } from '../discard/index' import type { TMappedResult } from '../mapped/index' @@ -40,14 +40,14 @@ import { IsMappedResult } from '../guard/kind' // ------------------------------------------------------------------ type TRemoveReadonly = T extends TReadonly ? S : T function RemoveReadonly(schema: T) { - return Discard(CloneType(schema), [ReadonlyKind]) + return CreateType(Discard(schema, [ReadonlyKind])) } // ------------------------------------------------------------------ // AddReadonly // ------------------------------------------------------------------ type TAddReadonly = T extends TReadonly ? TReadonly : Ensure> function AddReadonly(schema: T) { - return { ...CloneType(schema), [ReadonlyKind]: 'Readonly' } + return CreateType({ ...schema, [ReadonlyKind]: 'Readonly' }) } // prettier-ignore export type TReadonlyWithFlag = diff --git a/src/type/record/record.ts b/src/type/record/record.ts index cc6e9e7b8..e32ae7a26 100644 --- a/src/type/record/record.ts +++ b/src/type/record/record.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema } from '../schema/index' import type { Static } from '../static/index' import type { Evaluate, Ensure, Assert } from '../helpers/index' @@ -44,7 +45,6 @@ import { IsTemplateLiteralFinite, TIsTemplateLiteralFinite, type TTemplateLitera import { PatternStringExact, PatternNumberExact, PatternNeverExact } from '../patterns/index' import { IndexPropertyKeys } from '../indexed/index' import { Kind, Hint } from '../symbols/index' -import { CloneType } from '../clone/type' // ------------------------------------------------------------------ // ValueGuard // ------------------------------------------------------------------ @@ -58,12 +58,11 @@ import { IsInteger, IsLiteral, IsAny, IsNever, IsNumber, IsString, IsRegExp, IsT // ------------------------------------------------------------------ // prettier-ignore function RecordCreateFromPattern(pattern: string, T: TSchema, options: ObjectOptions): TRecord { - return { - ...options, + return CreateType({ [Kind]: 'Record', type: 'object', - patternProperties: { [pattern]: CloneType(T) } - } as never + patternProperties: { [pattern]: T } + }, options) as never } // ------------------------------------------------------------------ // RecordCreateFromKeys @@ -71,7 +70,7 @@ function RecordCreateFromPattern(pattern: string, T: TSchema, options: ObjectOpt // prettier-ignore function RecordCreateFromKeys(K: string[], T: TSchema, options: ObjectOptions): TObject { const Acc = {} as TProperties - for(const K2 of K) Acc[K2] = CloneType(T) + for(const K2 of K) Acc[K2] = T return Object(Acc, { ...options, [Hint]: 'Record' }) } // ------------------------------------------------------------------ diff --git a/src/type/recursive/recursive.ts b/src/type/recursive/recursive.ts index 46d28e98a..50df4f320 100644 --- a/src/type/recursive/recursive.ts +++ b/src/type/recursive/recursive.ts @@ -28,6 +28,7 @@ THE SOFTWARE. import type { TSchema, SchemaOptions } from '../schema/index' import { CloneType } from '../clone/type' +import { CreateType } from '../create/type' import { IsUndefined } from '../guard/value' import { Kind, Hint } from '../symbols/index' import { Static } from '../static/index' @@ -56,8 +57,8 @@ let Ordinal = 0 /** `[Json]` Creates a Recursive type */ export function Recursive(callback: (thisType: TThis) => T, options: SchemaOptions = {}): TRecursive { if (IsUndefined(options.$id)) (options as any).$id = `T${Ordinal++}` - const thisType = callback({ [Kind]: 'This', $ref: `${options.$id}` } as any) + const thisType = CloneType(callback({ [Kind]: 'This', $ref: `${options.$id}` } as any)) thisType.$id = options.$id // prettier-ignore - return CloneType({ ...options, [Hint]: 'Recursive', ...thisType }) as never + return CreateType({ [Hint]: 'Recursive', ...thisType }, options) as never } diff --git a/src/type/ref/ref.ts b/src/type/ref/ref.ts index 97fffe26f..3edd35b3d 100644 --- a/src/type/ref/ref.ts +++ b/src/type/ref/ref.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' import { Kind } from '../symbols/index' @@ -46,12 +47,8 @@ export function Ref(schema: T, options?: SchemaOptions): TRef /** `[Json]` Creates a Ref type. */ export function Ref($ref: string, options?: SchemaOptions): TRef /** `[Json]` Creates a Ref type. */ -export function Ref(unresolved: TSchema | string, options: SchemaOptions = {}) { - if (IsString(unresolved)) return { ...options, [Kind]: 'Ref', $ref: unresolved } +export function Ref(unresolved: TSchema | string, options?: SchemaOptions) { + if (IsString(unresolved)) return CreateType({ [Kind]: 'Ref', $ref: unresolved }, options) if (IsUndefined(unresolved.$id)) throw new Error('Reference target type must specify an $id') - return { - ...options, - [Kind]: 'Ref', - $ref: unresolved.$id!, - } + return CreateType({ [Kind]: 'Ref', $ref: unresolved.$id! }, options) } diff --git a/src/type/regexp/regexp.ts b/src/type/regexp/regexp.ts index c4d0030d0..6f005e696 100644 --- a/src/type/regexp/regexp.ts +++ b/src/type/regexp/regexp.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { SchemaOptions } from '../schema/index' import type { TSchema } from '../schema/index' import { IsString } from '../guard/value' @@ -50,7 +51,7 @@ export function RegExp(pattern: string, options?: RegExpOptions): TRegExp /** `[JavaScript]` Creates a RegExp type */ export function RegExp(regex: RegExp, options?: RegExpOptions): TRegExp /** `[JavaScript]` Creates a RegExp type */ -export function RegExp(unresolved: RegExp | string, options: RegExpOptions = {}) { +export function RegExp(unresolved: RegExp | string, options?: RegExpOptions) { const expr = IsString(unresolved) ? new globalThis.RegExp(unresolved) : unresolved - return { ...options, [Kind]: 'RegExp', type: 'RegExp', source: expr.source, flags: expr.flags } as never + return CreateType({ [Kind]: 'RegExp', type: 'RegExp', source: expr.source, flags: expr.flags }, options) as never } diff --git a/src/type/required/required-from-mapped-result.ts b/src/type/required/required-from-mapped-result.ts index 1e382ac3d..147508846 100644 --- a/src/type/required/required-from-mapped-result.ts +++ b/src/type/required/required-from-mapped-result.ts @@ -44,7 +44,7 @@ type TFromProperties< // prettier-ignore function FromProperties< P extends TProperties ->(P: P, options: SchemaOptions): TFromProperties

{ +>(P: P, options?: SchemaOptions): TFromProperties

{ const Acc = {} as TProperties for(const K2 of globalThis.Object.getOwnPropertyNames(P)) Acc[K2] = Required(P[K2], options) return Acc as never @@ -61,7 +61,7 @@ type TFromMappedResult< // prettier-ignore function FromMappedResult< R extends TMappedResult ->(R: R, options: SchemaOptions): TFromMappedResult { +>(R: R, options?: SchemaOptions): TFromMappedResult { return FromProperties(R.properties, options) as never } // ------------------------------------------------------------------ @@ -78,7 +78,7 @@ export type TRequiredFromMappedResult< export function RequiredFromMappedResult< R extends TMappedResult, P extends TProperties = TFromMappedResult ->(R: R, options: SchemaOptions): TMappedResult

{ +>(R: R, options?: SchemaOptions): TMappedResult

{ const P = FromMappedResult(R, options) return MappedResult(P) as never } diff --git a/src/type/required/required.ts b/src/type/required/required.ts index 9bbad39c7..807fff050 100644 --- a/src/type/required/required.ts +++ b/src/type/required/required.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Evaluate } from '../helpers/index' import type { TMappedResult } from '../mapped/index' @@ -36,11 +37,8 @@ import { type TRecursive } from '../recursive/index' import { type TIntersect, Intersect } from '../intersect/index' import { type TUnion, Union } from '../union/index' import { type TObject, type TProperties, Object } from '../object/index' - import { OptionalKind, TransformKind } from '../symbols/index' -import { CloneType } from '../clone/type' import { Discard } from '../discard/index' - import { RequiredFromMappedResult, type TRequiredFromMappedResult } from './required-from-mapped-result' // ------------------------------------------------------------------ @@ -106,12 +104,12 @@ export function Required(T: T, options?: SchemaOptions) /** `[Json]` Constructs a type where all properties are required */ export function Required(T: T, options?: SchemaOptions): TRequired /** `[Json]` Constructs a type where all properties are required */ -export function Required(T: T, options: SchemaOptions = {}) { +export function Required(T: T, options?: SchemaOptions): never { if (IsMappedResult(T)) { - return RequiredFromMappedResult(T, options) + return RequiredFromMappedResult(T, options) as never } else { const D = Discard(T, [TransformKind, '$id', 'required']) as TSchema - const R = CloneType(RequiredResolve(T) as any, options) - return { ...D, ...R } + const R = RequiredResolve(T) as any + return CreateType({ ...D, ...R }, options) as never } } diff --git a/src/type/rest/rest.ts b/src/type/rest/rest.ts index 86593daac..d437fa2da 100644 --- a/src/type/rest/rest.ts +++ b/src/type/rest/rest.ts @@ -30,7 +30,6 @@ import type { TSchema } from '../schema/index' import type { TIntersect } from '../intersect/index' import type { TUnion } from '../union/index' import type { TTuple } from '../tuple/index' -import { CloneRest } from '../clone/type' // ------------------------------------------------------------------ // TypeGuard @@ -41,16 +40,16 @@ import { IsIntersect, IsUnion, IsTuple } from '../guard/kind' // ------------------------------------------------------------------ // prettier-ignore type TRestResolve = - T extends TIntersect ? [...S] : - T extends TUnion ? [...S] : - T extends TTuple ? [...S] : + T extends TIntersect ? S : + T extends TUnion ? S : + T extends TTuple ? S : [] // prettier-ignore function RestResolve(T: T) { return ( - IsIntersect(T) ? CloneRest(T.allOf) : - IsUnion(T) ? CloneRest(T.anyOf) : - IsTuple(T) ? CloneRest(T.items ?? []) : + IsIntersect(T) ? T.allOf : + IsUnion(T) ? T.anyOf : + IsTuple(T) ? T.items ?? [] : [] ) as never } @@ -61,5 +60,5 @@ export type TRest = TRestResolve /** `[Json]` Extracts interior Rest elements from Tuple, Intersect and Union types */ export function Rest(T: T): TRest { - return CloneRest(RestResolve(T)) + return RestResolve(T) } diff --git a/src/type/return-type/return-type.ts b/src/type/return-type/return-type.ts index f3f843355..f868d2fcf 100644 --- a/src/type/return-type/return-type.ts +++ b/src/type/return-type/return-type.ts @@ -26,13 +26,13 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { SchemaOptions } from '../schema/index' import type { TFunction } from '../function/index' -import { CloneType } from '../clone/type' export type TReturnType = T['returns'] /** `[JavaScript]` Extracts the ReturnType from the given Function type */ -export function ReturnType>(schema: T, options: SchemaOptions = {}): TReturnType { - return CloneType(schema.returns, options) +export function ReturnType>(schema: T, options?: SchemaOptions): TReturnType { + return CreateType(schema.returns, options) as never } diff --git a/src/type/string/string.ts b/src/type/string/string.ts index 97ee88fc2..c1d6061b9 100644 --- a/src/type/string/string.ts +++ b/src/type/string/string.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -81,6 +82,6 @@ export interface TString extends TSchema, StringOptions { } /** `[Json]` Creates a String type */ -export function String(options: StringOptions = {}): TString { - return { ...options, [Kind]: 'String', type: 'string' } as never +export function String(options?: StringOptions): TString { + return CreateType({ [Kind]: 'String', type: 'string' }, options) as never } diff --git a/src/type/symbol/symbol.ts b/src/type/symbol/symbol.ts index f7e86697d..5a65b23b9 100644 --- a/src/type/symbol/symbol.ts +++ b/src/type/symbol/symbol.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -37,5 +38,5 @@ export interface TSymbol extends TSchema, SchemaOptions { } /** `[JavaScript]` Creates a Symbol type */ export function Symbol(options?: SchemaOptions): TSymbol { - return { ...options, [Kind]: 'Symbol', type: 'symbol' } as never + return CreateType({ [Kind]: 'Symbol', type: 'symbol' }, options) as never } diff --git a/src/type/template-literal/template-literal.ts b/src/type/template-literal/template-literal.ts index 8798b3083..7eadc534d 100644 --- a/src/type/template-literal/template-literal.ts +++ b/src/type/template-literal/template-literal.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Assert } from '../helpers/index' import type { TUnion } from '../union/index' @@ -94,9 +95,9 @@ export function TemplateLiteral(syntax: T, options?: SchemaOpt export function TemplateLiteral(kinds: [...T], options?: SchemaOptions): TTemplateLiteral /** `[Json]` Creates a TemplateLiteral type */ // prettier-ignore -export function TemplateLiteral(unresolved: TTemplateLiteralKind[] | string, options: SchemaOptions = {}): any { +export function TemplateLiteral(unresolved: TTemplateLiteralKind[] | string, options?: SchemaOptions): any { const pattern = IsString(unresolved) ? TemplateLiteralPattern(TemplateLiteralSyntax(unresolved)) : TemplateLiteralPattern(unresolved as TTemplateLiteralKind[]) - return { ...options, [Kind]: 'TemplateLiteral', type: 'string', pattern } + return CreateType({ [Kind]: 'TemplateLiteral', type: 'string', pattern }, options) } diff --git a/src/type/transform/transform.ts b/src/type/transform/transform.ts index 345726c61..eb7c561cd 100644 --- a/src/type/transform/transform.ts +++ b/src/type/transform/transform.ts @@ -29,7 +29,6 @@ THE SOFTWARE. import type { TSchema } from '../schema/index' import type { Static, StaticDecode } from '../static/index' import { TransformKind } from '../symbols/index' -import { CloneType } from '../clone/type' // ------------------------------------------------------------------ // TypeGuard @@ -58,10 +57,9 @@ export class TransformEncodeBuilder, StaticDecode>>(encode: E): TTransform> { - const schema = CloneType(this.schema) + public Encode, StaticDecode>>(encode: E): TTransform> { return ( - IsTransform(schema) ? this.EncodeTransform(encode, schema): this.EncodeSchema(encode, schema) + IsTransform(this.schema) ? this.EncodeTransform(encode, this.schema): this.EncodeSchema(encode, this.schema) ) as never } } diff --git a/src/type/tuple/tuple.ts b/src/type/tuple/tuple.ts index 193b3c840..67d564f9d 100644 --- a/src/type/tuple/tuple.ts +++ b/src/type/tuple/tuple.ts @@ -26,9 +26,9 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import type { Static } from '../static/index' -import { CloneRest } from '../clone/type' import { Kind } from '../symbols/index' // ------------------------------------------------------------------ @@ -52,13 +52,11 @@ export interface TTuple extends TSchema { maxItems: number } /** `[Json]` Creates a Tuple type */ -export function Tuple(items: [...T], options: SchemaOptions = {}): TTuple { - // return TupleResolver.Resolve(T) - const [additionalItems, minItems, maxItems] = [false, items.length, items.length] +export function Tuple(items: [...T], options?: SchemaOptions): TTuple { // prettier-ignore - return ( + return CreateType( items.length > 0 ? - { ...options, [Kind]: 'Tuple', type: 'array', items: CloneRest(items), additionalItems, minItems, maxItems } : - { ...options, [Kind]: 'Tuple', type: 'array', minItems, maxItems } - ) as never + { [Kind]: 'Tuple', type: 'array', items, additionalItems: false, minItems: items.length, maxItems: items.length } : + { [Kind]: 'Tuple', type: 'array', minItems: items.length, maxItems: items.length }, + options) as never } diff --git a/src/type/type/javascript.ts b/src/type/type/javascript.ts index ec87ac728..fad81ea22 100644 --- a/src/type/type/javascript.ts +++ b/src/type/type/javascript.ts @@ -49,19 +49,19 @@ import { Void, type TVoid } from '../void/index' /** JavaScript Type Builder with Static Resolution for TypeScript */ export class JavaScriptTypeBuilder extends JsonTypeBuilder { /** `[JavaScript]` Creates a AsyncIterator type */ - public AsyncIterator(items: T, options: SchemaOptions = {}): TAsyncIterator { + public AsyncIterator(items: T, options?: SchemaOptions): TAsyncIterator { return AsyncIterator(items, options) } /** `[JavaScript]` Constructs a type by recursively unwrapping Promise types */ - public Awaited(schema: T, options: SchemaOptions = {}): TAwaited { + public Awaited(schema: T, options?: SchemaOptions): TAwaited { return Awaited(schema, options) } /** `[JavaScript]` Creates a BigInt type */ - public BigInt(options: BigIntOptions = {}): TBigInt { + public BigInt(options?: BigIntOptions): TBigInt { return BigInt(options) } /** `[JavaScript]` Extracts the ConstructorParameters from the given Constructor type */ - public ConstructorParameters>(schema: T, options: SchemaOptions = {}): TConstructorParameters { + public ConstructorParameters>(schema: T, options?: SchemaOptions): TConstructorParameters { return ConstructorParameters(schema, options) } /** `[JavaScript]` Creates a Constructor type */ @@ -77,19 +77,19 @@ export class JavaScriptTypeBuilder extends JsonTypeBuilder { return FunctionType(parameters, returns, options) } /** `[JavaScript]` Extracts the InstanceType from the given Constructor type */ - public InstanceType>(schema: T, options: SchemaOptions = {}): TInstanceType { + public InstanceType>(schema: T, options?: SchemaOptions): TInstanceType { return InstanceType(schema, options) } /** `[JavaScript]` Creates an Iterator type */ - public Iterator(items: T, options: SchemaOptions = {}): TIterator { + public Iterator(items: T, options?: SchemaOptions): TIterator { return Iterator(items, options) } /** `[JavaScript]` Extracts the Parameters from the given Function type */ - public Parameters>(schema: T, options: SchemaOptions = {}): TParameters { + public Parameters>(schema: T, options?: SchemaOptions): TParameters { return Parameters(schema, options) } /** `[JavaScript]` Creates a Promise type */ - public Promise(item: T, options: SchemaOptions = {}): TPromise { + public Promise(item: T, options?: SchemaOptions): TPromise { return Promise(item, options) } /** `[JavaScript]` Creates a RegExp type */ @@ -97,11 +97,11 @@ export class JavaScriptTypeBuilder extends JsonTypeBuilder { /** `[JavaScript]` Creates a RegExp type */ public RegExp(regex: RegExp, options?: RegExpOptions): TRegExp /** `[JavaScript]` Creates a RegExp type */ - public RegExp(unresolved: string | RegExp, options: RegExpOptions = {}) { + public RegExp(unresolved: string | RegExp, options?: RegExpOptions) { return RegExp(unresolved as any, options) } /** `[JavaScript]` Extracts the ReturnType from the given Function type */ - public ReturnType>(schema: T, options: SchemaOptions = {}): TReturnType { + public ReturnType>(schema: T, options?: SchemaOptions): TReturnType { return ReturnType(schema, options) } /** `[JavaScript]` Creates a Symbol type */ @@ -109,15 +109,15 @@ export class JavaScriptTypeBuilder extends JsonTypeBuilder { return Symbol(options) } /** `[JavaScript]` Creates a Undefined type */ - public Undefined(options: SchemaOptions = {}): TUndefined { + public Undefined(options?: SchemaOptions): TUndefined { return Undefined(options) } /** `[JavaScript]` Creates a Uint8Array type */ - public Uint8Array(options: Uint8ArrayOptions = {}): TUint8Array { + public Uint8Array(options?: Uint8ArrayOptions): TUint8Array { return Uint8Array(options) } /** `[JavaScript]` Creates a Void type */ - public Void(options: SchemaOptions = {}): TVoid { + public Void(options?: SchemaOptions): TVoid { return Void(options) } } diff --git a/src/type/type/json.ts b/src/type/type/json.ts index 3d1854005..f9a1ae741 100644 --- a/src/type/type/json.ts +++ b/src/type/type/json.ts @@ -114,19 +114,19 @@ export class JsonTypeBuilder { // Types // ------------------------------------------------------------------------ /** `[Json]` Creates an Any type */ - public Any(options: SchemaOptions = {}): TAny { + public Any(options?: SchemaOptions): TAny { return Any(options) } /** `[Json]` Creates an Array type */ - public Array(schema: T, options: ArrayOptions = {}): TArray { + public Array(schema: T, options?: ArrayOptions): TArray { return Array(schema, options) } /** `[Json]` Creates a Boolean type */ - public Boolean(options: SchemaOptions = {}): TBoolean { + public Boolean(options?: SchemaOptions): TBoolean { return Boolean(options) } /** `[Json]` Intrinsic function to Capitalize LiteralString types */ - public Capitalize(schema: T, options: SchemaOptions = {}): TCapitalize { + public Capitalize(schema: T, options?: SchemaOptions): TCapitalize { return Capitalize(schema, options) } /** `[Json]` Creates a Composite object type */ @@ -134,7 +134,7 @@ export class JsonTypeBuilder { return Composite(schemas, options) // (error) TS 5.4.0-dev - review TComposite implementation } /** `[JavaScript]` Creates a readonly const type from the given value. */ - public Const(value: T, options: SchemaOptions = {}): TConst { + public Const(value: T, options?: SchemaOptions): TConst { return Const(value, options) } /** `[Json]` Creates a dereferenced type */ @@ -142,7 +142,7 @@ export class JsonTypeBuilder { return Deref(schema, references) } /** `[Json]` Creates a Enum type */ - public Enum>(item: T, options: SchemaOptions = {}): TEnum { + public Enum>(item: T, options?: SchemaOptions): TEnum { return Enum(item, options) } /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ @@ -152,7 +152,7 @@ export class JsonTypeBuilder { /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ public Exclude(unionType: L, excludedMembers: R, options?: SchemaOptions): TExclude /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ - public Exclude(unionType: TSchema, excludedMembers: TSchema, options: SchemaOptions = {}): any { + public Exclude(unionType: TSchema, excludedMembers: TSchema, options?: SchemaOptions): any { return Exclude(unionType, excludedMembers, options) } /** `[Json]` Creates a Conditional type */ @@ -162,7 +162,7 @@ export class JsonTypeBuilder { /** `[Json]` Creates a Conditional type */ public Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions): TExtends /** `[Json]` Creates a Conditional type */ - public Extends(L: L, R: R, T: T, F: F, options: SchemaOptions = {}) { + public Extends(L: L, R: R, T: T, F: F, options?: SchemaOptions) { return Extends(L, R, T, F, options) } /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ @@ -172,7 +172,7 @@ export class JsonTypeBuilder { /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ public Extract(type: L, union: R, options?: SchemaOptions): TExtract /** `[Json]` Constructs a type by extracting from type all union members that are assignable to union */ - public Extract(type: TSchema, union: TSchema, options: SchemaOptions = {}): any { + public Extract(type: TSchema, union: TSchema, options?: SchemaOptions): any { return Extract(type, union, options) } /** `[Json]` Returns an Indexed property type for the given keys */ @@ -184,15 +184,15 @@ export class JsonTypeBuilder { /** `[Json]` Returns an Indexed property type for the given keys */ public Index(T: T, K: readonly [...K], options?: SchemaOptions): TIndex /** `[Json]` Returns an Indexed property type for the given keys */ - public Index(schema: TSchema, unresolved: any, options: SchemaOptions = {}): any { + public Index(schema: TSchema, unresolved: any, options?: SchemaOptions): any { return Index(schema, unresolved, options) } /** `[Json]` Creates an Integer type */ - public Integer(options: IntegerOptions = {}): TInteger { + public Integer(options?: IntegerOptions): TInteger { return Integer(options) } /** `[Json]` Creates an Intersect type */ - public Intersect(T: [...T], options: IntersectOptions = {}): Intersect { + public Intersect(T: [...T], options?: IntersectOptions): Intersect { return Intersect(T, options) } /** `[Json]` Creates a KeyOf type */ @@ -200,15 +200,15 @@ export class JsonTypeBuilder { /** `[Json]` Creates a KeyOf type */ public KeyOf(schema: T, options?: SchemaOptions): TKeyOf /** `[Json]` Creates a KeyOf type */ - public KeyOf(schema: TSchema, options: SchemaOptions = {}): any { + public KeyOf(schema: TSchema, options?: SchemaOptions): any { return KeyOf(schema, options) } /** `[Json]` Creates a Literal type */ - public Literal(value: T, options: SchemaOptions = {}): TLiteral { + public Literal(value: T, options?: SchemaOptions): TLiteral { return Literal(value, options) } /** `[Json]` Intrinsic function to Lowercase LiteralString types */ - public Lowercase(schema: T, options: SchemaOptions = {}): TLowercase { + public Lowercase(schema: T, options?: SchemaOptions): TLowercase { return Lowercase(schema, options) } /** `[Json]` Creates a Mapped object type */ @@ -216,11 +216,11 @@ export class JsonTypeBuilder { /** `[Json]` Creates a Mapped object type */ public Mapped = TMappedFunction, R extends TMapped = TMapped>(key: [...K], map: F, options?: ObjectOptions): R /** `[Json]` Creates a Mapped object type */ - public Mapped(key: any, map: TMappedFunction, options: ObjectOptions = {}): any { + public Mapped(key: any, map: TMappedFunction, options?: ObjectOptions): any { return Mapped(key, map, options) } /** `[Json]` Creates a Never type */ - public Never(options: SchemaOptions = {}): TNever { + public Never(options?: SchemaOptions): TNever { return Never(options) } /** `[Json]` Creates a Not type */ @@ -228,15 +228,15 @@ export class JsonTypeBuilder { return Not(schema, options) } /** `[Json]` Creates a Null type */ - public Null(options: SchemaOptions = {}): TNull { + public Null(options?: SchemaOptions): TNull { return Null(options) } /** `[Json]` Creates a Number type */ - public Number(options: NumberOptions = {}): TNumber { + public Number(options?: NumberOptions): TNumber { return Number(options) } /** `[Json]` Creates an Object type */ - public Object(properties: T, options: ObjectOptions = {}): TObject { + public Object(properties: T, options?: ObjectOptions): TObject { return Object(properties, options) } /** `[Json]` Constructs a type whose keys are omitted from the given type */ @@ -248,7 +248,7 @@ export class JsonTypeBuilder { /** `[Json]` Constructs a type whose keys are omitted from the given type */ public Omit(T: T, K: readonly [...K], options?: SchemaOptions): TOmit /** `[Json]` Constructs a type whose keys are omitted from the given type */ - public Omit(schema: TSchema, unresolved: any, options: SchemaOptions = {}): any { + public Omit(schema: TSchema, unresolved: any, options?: SchemaOptions): any { return Omit(schema, unresolved, options) } /** `[Json]` Constructs a type where all properties are optional */ @@ -256,7 +256,7 @@ export class JsonTypeBuilder { /** `[Json]` Constructs a type where all properties are optional */ public Partial(schema: T, options?: ObjectOptions): TPartial /** `[Json]` Constructs a type where all properties are optional */ - public Partial(schema: TSchema, options: ObjectOptions = {}): any { + public Partial(schema: TSchema, options?: ObjectOptions): any { return Partial(schema, options) } /** `[Json]` Constructs a type whose keys are picked from the given type */ @@ -268,15 +268,15 @@ export class JsonTypeBuilder { /** `[Json]` Constructs a type whose keys are picked from the given type */ public Pick(T: T, K: readonly [...K], options?: SchemaOptions): TPick /** `[Json]` Constructs a type whose keys are picked from the given type */ - public Pick(schema: TSchema, unresolved: any, options: SchemaOptions = {}): any { + public Pick(schema: TSchema, unresolved: any, options?: SchemaOptions): any { return Pick(schema, unresolved, options) } /** `[Json]` Creates a Record type */ - public Record(key: K, schema: T, options: ObjectOptions = {}): TRecordOrObject { + public Record(key: K, schema: T, options?: ObjectOptions): TRecordOrObject { return Record(key, schema, options) } /** `[Json]` Creates a Recursive type */ - public Recursive(callback: (thisType: TThis) => T, options: SchemaOptions = {}): TRecursive { + public Recursive(callback: (thisType: TThis) => T, options?: SchemaOptions): TRecursive { return Recursive(callback, options) } /** `[Json]` Creates a Ref type. The referenced type must contain a $id */ @@ -284,7 +284,7 @@ export class JsonTypeBuilder { /** `[Json]` Creates a Ref type. */ public Ref($ref: string, options?: SchemaOptions): TRef /** `[Json]` Creates a Ref type. */ - public Ref(unresolved: TSchema | string, options: SchemaOptions = {}) { + public Ref(unresolved: TSchema | string, options?: SchemaOptions) { return Ref(unresolved as any, options) } /** `[Json]` Constructs a type where all properties are required */ @@ -292,7 +292,7 @@ export class JsonTypeBuilder { /** `[Json]` Constructs a type where all properties are required */ public Required(schema: T, options?: ObjectOptions): TRequired /** `[Json]` Constructs a type where all properties are required */ - public Required(schema: TSchema, options: ObjectOptions = {}): any { + public Required(schema: TSchema, options?: ObjectOptions): any { return Required(schema, options) } /** `[Json]` Extracts interior Rest elements from Tuple, Intersect and Union types */ @@ -300,7 +300,7 @@ export class JsonTypeBuilder { return Rest(schema) } /** `[Json]` Creates a String type */ - public String(options: StringOptions = {}): TString { + public String(options?: StringOptions): TString { return String(options) } /** `[Json]` Creates a TemplateLiteral type from template dsl string */ @@ -308,7 +308,7 @@ export class JsonTypeBuilder { /** `[Json]` Creates a TemplateLiteral type */ public TemplateLiteral(kinds: [...T], options?: SchemaOptions): TTemplateLiteral /** `[Json]` Creates a TemplateLiteral type */ - public TemplateLiteral(unresolved: TTemplateLiteralKind[] | string, options: SchemaOptions = {}) { + public TemplateLiteral(unresolved: TTemplateLiteralKind[] | string, options?: SchemaOptions) { return TemplateLiteral(unresolved as any, options) } /** `[Json]` Creates a Transform type */ @@ -316,27 +316,27 @@ export class JsonTypeBuilder { return Transform(schema) } /** `[Json]` Creates a Tuple type */ - public Tuple(items: [...T], options: SchemaOptions = {}): TTuple { + public Tuple(items: [...T], options?: SchemaOptions): TTuple { return Tuple(items, options) } /** `[Json]` Intrinsic function to Uncapitalize LiteralString types */ - public Uncapitalize(schema: T, options: SchemaOptions = {}): TUncapitalize { + public Uncapitalize(schema: T, options?: SchemaOptions): TUncapitalize { return Uncapitalize(schema, options) } /** `[Json]` Creates a Union type */ - public Union(schemas: [...T], options: SchemaOptions = {}): Union { + public Union(schemas: [...T], options?: SchemaOptions): Union { return Union(schemas, options) } /** `[Json]` Creates an Unknown type */ - public Unknown(options: SchemaOptions = {}): TUnknown { + public Unknown(options?: SchemaOptions): TUnknown { return Unknown(options) } /** `[Json]` Creates a Unsafe type that will infers as the generic argument T */ - public Unsafe(options: UnsafeOptions = {}): TUnsafe { + public Unsafe(options?: UnsafeOptions): TUnsafe { return Unsafe(options) } /** `[Json]` Intrinsic function to Uppercase LiteralString types */ - public Uppercase(schema: T, options: SchemaOptions = {}): TUppercase { + public Uppercase(schema: T, options?: SchemaOptions): TUppercase { return Uppercase(schema, options) } } diff --git a/src/type/uint8array/uint8array.ts b/src/type/uint8array/uint8array.ts index 55458346c..09c57ab01 100644 --- a/src/type/uint8array/uint8array.ts +++ b/src/type/uint8array/uint8array.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -39,6 +40,6 @@ export interface TUint8Array extends TSchema, Uint8ArrayOptions { type: 'uint8array' } /** `[JavaScript]` Creates a Uint8Array type */ -export function Uint8Array(options: Uint8ArrayOptions = {}): TUint8Array { - return { ...options, [Kind]: 'Uint8Array', type: 'Uint8Array' } as never +export function Uint8Array(options?: Uint8ArrayOptions): TUint8Array { + return CreateType({ [Kind]: 'Uint8Array', type: 'Uint8Array' }, options) as never } diff --git a/src/type/undefined/undefined.ts b/src/type/undefined/undefined.ts index bbba2b4bf..efd2a7649 100644 --- a/src/type/undefined/undefined.ts +++ b/src/type/undefined/undefined.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -35,6 +36,6 @@ export interface TUndefined extends TSchema { type: 'undefined' } /** `[JavaScript]` Creates a Undefined type */ -export function Undefined(options: SchemaOptions = {}): TUndefined { - return { ...options, [Kind]: 'Undefined', type: 'undefined' } as never +export function Undefined(options?: SchemaOptions): TUndefined { + return CreateType({ [Kind]: 'Undefined', type: 'undefined' }, options) as never } diff --git a/src/type/union/union-create.ts b/src/type/union/union-create.ts index 86093fe58..856f1ffc4 100644 --- a/src/type/union/union-create.ts +++ b/src/type/union/union-create.ts @@ -27,10 +27,10 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ import type { TSchema, SchemaOptions } from '../schema/index' -import { CloneRest } from '../clone/type' +import { CreateType } from '../create/type' import { TUnion } from './union-type' import { Kind } from '../symbols/index' -export function UnionCreate(T: [...T], options: SchemaOptions): TUnion { - return { ...options, [Kind]: 'Union', anyOf: CloneRest(T) } as never +export function UnionCreate(T: [...T], options?: SchemaOptions): TUnion { + return CreateType({ [Kind]: 'Union', anyOf: T }, options) as never } diff --git a/src/type/union/union-evaluated.ts b/src/type/union/union-evaluated.ts index afbf4714f..9e4004a20 100644 --- a/src/type/union/union-evaluated.ts +++ b/src/type/union/union-evaluated.ts @@ -26,9 +26,9 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { SchemaOptions, TSchema } from '../schema/index' import { OptionalKind } from '../symbols/index' -import { CloneType } from '../clone/type' import { Discard } from '../discard/index' import { Never, type TNever } from '../never/index' import { Optional, type TOptional } from '../optional/index' @@ -95,7 +95,7 @@ type TResolveUnion ) // prettier-ignore -function ResolveUnion(T: T, options: SchemaOptions): TResolveUnion { +function ResolveUnion(T: T, options?: SchemaOptions): TResolveUnion { return ( IsUnionOptional(T) ? Optional(UnionCreate(RemoveOptionalFromRest(T) as TSchema[], options)) @@ -112,11 +112,11 @@ export type TUnionEvaluated = ( TResolveUnion ) /** `[Json]` Creates an evaluated Union type */ -export function UnionEvaluated>(T: [...T], options: SchemaOptions = {}): R { +export function UnionEvaluated>(T: [...T], options?: SchemaOptions): R { // prettier-ignore return ( T.length === 0 ? Never(options) : - T.length === 1 ? CloneType(T[0], options) : + T.length === 1 ? CreateType(T[0], options) : ResolveUnion(T, options) ) as never } diff --git a/src/type/union/union.ts b/src/type/union/union.ts index 2024ad8bb..a057141c8 100644 --- a/src/type/union/union.ts +++ b/src/type/union/union.ts @@ -29,7 +29,7 @@ THE SOFTWARE. import type { TSchema, SchemaOptions } from '../schema/index' import { type TNever, Never } from '../never/index' import type { TUnion } from './union-type' -import { CloneType } from '../clone/type' +import { CreateType } from '../create/type' import { UnionCreate } from './union-create' // prettier-ignore @@ -39,11 +39,11 @@ export type Union = ( TUnion ) /** `[Json]` Creates a Union type */ -export function Union(T: [...T], options: SchemaOptions = {}): Union { +export function Union(T: [...T], options?: SchemaOptions): Union { // prettier-ignore return ( T.length === 0 ? Never(options) : - T.length === 1 ? CloneType(T[0], options) : + T.length === 1 ? CreateType(T[0], options) : UnionCreate(T, options) ) as Union } diff --git a/src/type/unknown/unknown.ts b/src/type/unknown/unknown.ts index 28dce27be..f91f9613d 100644 --- a/src/type/unknown/unknown.ts +++ b/src/type/unknown/unknown.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -34,9 +35,6 @@ export interface TUnknown extends TSchema { static: unknown } /** `[Json]` Creates an Unknown type */ -export function Unknown(options: SchemaOptions = {}): TUnknown { - return { - ...options, - [Kind]: 'Unknown', - } as never +export function Unknown(options?: SchemaOptions): TUnknown { + return CreateType({ [Kind]: 'Unknown' }, options) as never } diff --git a/src/type/unsafe/unsafe.ts b/src/type/unsafe/unsafe.ts index f70ec80fc..4a52650d8 100644 --- a/src/type/unsafe/unsafe.ts +++ b/src/type/unsafe/unsafe.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -38,8 +39,5 @@ export interface TUnsafe extends TSchema { } /** `[Json]` Creates a Unsafe type that will infers as the generic argument T */ export function Unsafe(options: UnsafeOptions = {}): TUnsafe { - return { - ...options, - [Kind]: options[Kind] ?? 'Unsafe', - } as never + return CreateType({ [Kind]: options[Kind] ?? 'Unsafe' }, options) as never } diff --git a/src/type/void/void.ts b/src/type/void/void.ts index c7f704d13..0672480b9 100644 --- a/src/type/void/void.ts +++ b/src/type/void/void.ts @@ -26,6 +26,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ +import { CreateType } from '../create/type' import type { TSchema, SchemaOptions } from '../schema/index' import { Kind } from '../symbols/index' @@ -35,10 +36,6 @@ export interface TVoid extends TSchema { type: 'void' } /** `[JavaScript]` Creates a Void type */ -export function Void(options: SchemaOptions = {}): TVoid { - return { - ...options, - [Kind]: 'Void', - type: 'void', - } as never +export function Void(options?: SchemaOptions): TVoid { + return CreateType({ [Kind]: 'Void', type: 'void' }, options) as never } diff --git a/test/runtime/index.ts b/test/runtime/index.ts index fb4f897fd..16011ae88 100644 --- a/test/runtime/index.ts +++ b/test/runtime/index.ts @@ -1,3 +1,10 @@ +import { TypeSystemPolicy } from '@sinclair/typebox/system' + +// ------------------------------------------------------------------ +// InstanceMode: Freeze (Detect Unintended Side Effects) +// ------------------------------------------------------------------ +TypeSystemPolicy.InstanceMode = 'default' + import './compiler/index' import './compiler-ajv/index' import './errors/index' diff --git a/test/runtime/type/guard/type/ref.ts b/test/runtime/type/guard/type/ref.ts index ab8f109bf..c864cbd4f 100644 --- a/test/runtime/type/guard/type/ref.ts +++ b/test/runtime/type/guard/type/ref.ts @@ -1,5 +1,5 @@ import { TypeGuard } from '@sinclair/typebox' -import { Type } from '@sinclair/typebox' +import { Type, CloneType } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TRef', () => { @@ -14,7 +14,7 @@ describe('guard/type/TRef', () => { }) it('Should not guard for TRef with invalid $ref', () => { const T = Type.Number({ $id: 'T' }) - const S = Type.Ref(T) + const S = CloneType(Type.Ref(T)) // @ts-ignore S.$ref = 1 const R = TypeGuard.IsRef(S) diff --git a/test/runtime/type/guard/type/template-literal.ts b/test/runtime/type/guard/type/template-literal.ts index 63fb736aa..f00db33c2 100644 --- a/test/runtime/type/guard/type/template-literal.ts +++ b/test/runtime/type/guard/type/template-literal.ts @@ -1,5 +1,5 @@ import { TypeGuard } from '@sinclair/typebox' -import { Type, TemplateLiteralGenerate } from '@sinclair/typebox' +import { Type, CloneType, TemplateLiteralGenerate } from '@sinclair/typebox' import { Assert } from '../../../assert/index' describe('guard/type/TTemplateLiteral', () => { @@ -33,13 +33,13 @@ describe('guard/type/TTemplateLiteral', () => { Assert.IsTrue(R) }) it('Should not guard for missing ^ expression prefix', () => { - const T = Type.TemplateLiteral([Type.Literal('hello')]) + const T = CloneType(Type.TemplateLiteral([Type.Literal('hello')])) // @ts-ignore T.pattern = T.pattern.slice(1) Assert.IsFalse(TypeGuard.IsTemplateLiteral(T)) }) it('Should not guard for missing $ expression postfix', () => { - const T = Type.TemplateLiteral([Type.Literal('hello')]) + const T = CloneType(Type.TemplateLiteral([Type.Literal('hello')])) // @ts-ignore T.pattern = T.pattern.slice(0, T.pattern.length - 1) Assert.IsFalse(TypeGuard.IsTemplateLiteral(T))