diff --git a/package-lock.json b/package-lock.json index 78a0102..154b955 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sinclair/typebox", - "version": "0.32.5", + "version": "0.32.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sinclair/typebox", - "version": "0.32.5", + "version": "0.32.6", "license": "MIT", "devDependencies": { "@arethetypeswrong/cli": "^0.13.2", diff --git a/package.json b/package.json index 930e2f3..afe9e95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sinclair/typebox", - "version": "0.32.5", + "version": "0.32.6", "description": "Json Schema Type Builder with Static Type Resolution for TypeScript", "keywords": [ "typescript", diff --git a/src/index.ts b/src/index.ts index 779964f..4f582c5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -41,7 +41,7 @@ export { TypeBoxError } from './type/error/index' export { Any, type TAny } from './type/any/index' export { Array, type TArray, type ArrayOptions } from './type/array/index' export { AsyncIterator, type TAsyncIterator } from './type/async-iterator/index' -export { Awaited, type TAwaited } from './type/awaited/index' +export { Awaited, type TAwaited, type TAwaitedResolve } from './type/awaited/index' export { BigInt, type TBigInt, type BigIntOptions } from './type/bigint/index' export { Boolean, type TBoolean } from './type/boolean/index' export { Composite, type TComposite } from './type/composite/index' @@ -52,7 +52,7 @@ export { Date, type TDate, type DateOptions } from './type/date/index' export { Deref, type TDeref } from './type/deref/index' export { Enum, type TEnum } from './type/enum/index' export { Exclude, type TExclude, type TExcludeFromMappedResult } from './type/exclude/index' -export { Extends, type TExtends, type ExtendsFromMappedResult, type ExtendsFromMappedKey, ExtendsCheck, ExtendsResult, ExtendsUndefinedCheck } from './type/extends/index' +export { Extends, ExtendsCheck, ExtendsResult, ExtendsUndefinedCheck, type TExtends, type ExtendsFromMappedResult, type ExtendsFromMappedKey } from './type/extends/index' export { Extract, type TExtract, type TExtractFromMappedResult } from './type/extract/index' export { Function, type TFunction } from './type/function/index' export { Increment, type Assert, type AssertType, type AssertRest, type AssertProperties, type Ensure, type Evaluate, type TupleToIntersect, type TupleToUnion, type UnionToTuple } from './type/helpers/index' @@ -62,23 +62,23 @@ export { Integer, type TInteger, type IntegerOptions } from './type/integer/inde export { Intersect, IntersectEvaluated, type TIntersect, type TIntersectEvaluated, type IntersectOptions } from './type/intersect/index' export { Iterator, type TIterator } from './type/iterator/index' export { Intrinsic, IntrinsicFromMappedKey, type TIntrinsic, Capitalize, type TCapitalize, Lowercase, type TLowercase, Uncapitalize, type TUncapitalize, Uppercase, type TUppercase } from './type/intrinsic/index' -export { KeyOf, type TKeyOf, type KeyOfFromMappedResult, KeyOfPropertyKeys, KeyOfPattern } from './type/keyof/index' +export { KeyOf, KeyOfPropertyKeys, KeyOfPropertyKeysToRest, KeyOfFromMappedResult, KeyOfPattern, type TKeyOf, type TKeyOfPropertyKeys, type TKeyOfPropertyKeysToRest, type TKeyOfFromMappedResult } from './type/keyof/index' export { Literal, type TLiteral, type TLiteralValue } from './type/literal/index' -export { Mapped, MappedKey, MappedResult, type TMapped, type TMappedKey, type TMappedResult, type TMappedFunction } from './type/mapped/index' +export { Mapped, MappedKey, MappedResult, MappedFunctionReturnType, type TMapped, type TMappedKey, type TMappedResult, type TMappedFunction, type TMappedFunctionReturnType } from './type/mapped/index' export { Never, type TNever } from './type/never/index' export { Not, type TNot } from './type/not/index' export { Null, type TNull } from './type/null/index' export { Number, type TNumber, type NumberOptions } from './type/number/index' export { Object, type TObject, type TProperties, type ObjectOptions } from './type/object/index' -export { Omit, type TOmit, type TOmitFromMappedKey, type TOmitFromMappedResult } from './type/omit/index' +export { Omit, type TOmit, type TOmitResolve, type TOmitFromMappedKey, type TOmitFromMappedResult } from './type/omit/index' export { Optional, OptionalFromMappedResult, type TOptional, type TOptionalWithFlag, type TOptionalFromMappedResult } from './type/optional/index' export { Parameters, type TParameters } from './type/parameters/index' export { Partial, PartialFromMappedResult, type TPartial, type TPartialFromMappedResult } from './type/partial/index' -export { Pick, type TPick, type TPickFromMappedKey, type TPickFromMappedResult } from './type/pick/index' +export { Pick, type TPick, type TPickResolve, type TPickFromMappedKey, type TPickFromMappedResult } from './type/pick/index' export { Promise, type TPromise } from './type/promise/index' export { Readonly, ReadonlyFromMappedResult, type TReadonly, type TReadonlyWithFlag, type TReadonlyFromMappedResult } from './type/readonly/index' export { ReadonlyOptional, type TReadonlyOptional } from './type/readonly-optional/index' -export { Record, type TRecord } from './type/record/index' +export { Record, type TRecord, type TRecordOrObject } from './type/record/index' export { Recursive, type TRecursive, type TThis } from './type/recursive/index' export { Ref, type TRef } from './type/ref/index' export { RegExp, type TRegExp } from './type/regexp/index' @@ -86,7 +86,7 @@ export { Required, type TRequired, type TRequiredFromMappedResult } from './type export { Rest, type TRest } from './type/rest/index' export { ReturnType, type TReturnType } from './type/return-type/index' export { type TSchema, type TKind, type SchemaOptions, type TAnySchema } from './type/schema/index' -export { type Static, type StaticDecode, type StaticEncode } from './type/static/index' +export { type Static, type StaticDecode, type StaticEncode, type TDecodeType, type TDecodeRest, type TDecodeProperties } from './type/static/index' export { Strict } from './type/strict/index' export { String, type TString, type StringOptions, type StringFormatOption, type StringContentEncodingOption } from './type/string/index' export { Symbol, type TSymbol, type TSymbolValue as SymbolValue } from './type/symbol/index' @@ -98,6 +98,8 @@ export { TemplateLiteralParseExact, TemplateLiteralGenerate, TemplateLiteralExpressionGenerate, + TemplateLiteralSyntax, + type TTemplateLiteralSyntax, type TTemplateLiteral, type TIsTemplateLiteralFinite, type TTemplateLiteralGenerate, diff --git a/src/type/awaited/awaited.ts b/src/type/awaited/awaited.ts index 7a17df3..c782487 100644 --- a/src/type/awaited/awaited.ts +++ b/src/type/awaited/awaited.ts @@ -42,11 +42,11 @@ import { IsIntersect, IsUnion, IsPromise } from '../guard/type' // prettier-ignore type TFromRest = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? TFromRest]> + ? TFromRest]> : Acc // prettier-ignore function FromRest(T: [...T]) : TFromRest { - return T.map(L => FromSchema(L)) as TFromRest + return T.map(L => AwaitedResolve(L)) as TFromRest } // ---------------------------------------------------------------- // FromIntersect @@ -69,37 +69,37 @@ function FromUnion(T: [...T]): TFromUnion { // ---------------------------------------------------------------- // Promise // ---------------------------------------------------------------- -type TFromPromise = TFromSchema +type TFromPromise = TAwaitedResolve // prettier-ignore function FromPromise(T: T): TFromPromise { - return FromSchema(T) as TFromPromise + return AwaitedResolve(T) as TFromPromise } // ---------------------------------------------------------------- // FromSchema // ---------------------------------------------------------------- // prettier-ignore -type TFromSchema = +export type TAwaitedResolve = T extends TIntersect ? TIntersect> : T extends TUnion ? TUnion> : - T extends TPromise ? TFromSchema : + T extends TPromise ? TAwaitedResolve : T // prettier-ignore -function FromSchema(T: T): TFromSchema { +export function AwaitedResolve(T: T): TAwaitedResolve { return ( IsIntersect(T) ? FromIntersect(T.allOf) : IsUnion(T) ? FromUnion(T.anyOf) : IsPromise(T) ? FromPromise(T.item) : T - ) as TFromSchema + ) as TAwaitedResolve } // ------------------------------------------------------------------ // TAwaited // ------------------------------------------------------------------ // prettier-ignore export type TAwaited = ( - TFromSchema + TAwaitedResolve ) /** `[JavaScript]` Constructs a type by recursively unwrapping Promise types */ -export function Awaited(T: T, options: SchemaOptions = {}): TFromSchema { - return CloneType(FromSchema(T), options) +export function Awaited(T: T, options: SchemaOptions = {}): TAwaitedResolve { + return CloneType(AwaitedResolve(T), options) } diff --git a/src/type/composite/composite.ts b/src/type/composite/composite.ts index ae99401..b4dc847 100644 --- a/src/type/composite/composite.ts +++ b/src/type/composite/composite.ts @@ -27,12 +27,11 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ import type { TSchema } from '../schema/index' -import type { UnionToTuple, Assert, Evaluate } from '../helpers/index' +import type { UnionToTuple, Assert, Ensure, Evaluate } from '../helpers/index' import { Object, type TObject, type TProperties, type ObjectOptions } from '../object/index' import { Intersect, type TIntersect } from '../intersect/index' import { Index, type TIndex } from '../indexed/index' import { KeyOfPropertyKeys } from '../keyof/index' -import { CloneType } from '../clone/type' // ------------------------------------------------------------------ // TCompositeKeys @@ -54,22 +53,18 @@ type TCompositeIndex, K extends string[], Acc ex type TCompositeReduce = UnionToTuple> extends infer K ? Evaluate, Assert>> : {} // ^ indexed via intersection of T -// prettier-ignore -type TCompositeResolve = TIntersect extends TIntersect - ? TObject> - : TObject<{}> -function CompositeResolve(T: [...T]): TCompositeResolve { - const intersect: TSchema = Intersect(T, {}) - const keys = KeyOfPropertyKeys(intersect) as string[] - const properties = keys.reduce((acc, key) => ({ ...acc, [key]: Index(intersect, [key]) }), {} as TProperties) - return Object(properties) as TCompositeResolve -} // ------------------------------------------------------------------ // TComposite // ------------------------------------------------------------------ -export type TComposite = TCompositeResolve +// prettier-ignore +export type TComposite = TIntersect extends TIntersect + ? Ensure>> + : Ensure> /** `[Json]` Creates a Composite object type */ export function Composite(T: [...T], options?: ObjectOptions): TComposite { - return CloneType(CompositeResolve(T) as TObject, options) as TComposite + const intersect: TSchema = Intersect(T, {}) + const keys = KeyOfPropertyKeys(intersect) as string[] + const properties = keys.reduce((acc, key) => ({ ...acc, [key]: Index(intersect, [key]) }), {} as TProperties) + return Object(properties, options) as TComposite } diff --git a/src/type/exclude/exclude.ts b/src/type/exclude/exclude.ts index e69ef1b..d82bdf3 100644 --- a/src/type/exclude/exclude.ts +++ b/src/type/exclude/exclude.ts @@ -44,53 +44,44 @@ import { ExcludeFromMappedResult, type TExcludeFromMappedResult } from './exclud // ------------------------------------------------------------------ import { IsMappedResult, IsTemplateLiteral, IsUnion } from '../guard/type' // ------------------------------------------------------------------ -// ExcludeResolve +// ExcludeTemplateLiteral // ------------------------------------------------------------------ // prettier-ignore type TExcludeTemplateLiteralResult = TUnionEvaluated }[T]>>> // prettier-ignore -type TExcludeTemplateLiteral = ( - Exclude, Static> extends infer S ? TExcludeTemplateLiteralResult> : never +type TExcludeTemplateLiteral = ( + Exclude, Static> extends infer S ? TExcludeTemplateLiteralResult> : never ) +// ------------------------------------------------------------------ +// ExcludeRest +// ------------------------------------------------------------------ // prettier-ignore -type TExcludeArray = AssertRest> extends Static ? never : T[K] +type TExcludeRest = AssertRest> extends Static ? never : L[K] }[number]>> extends infer R extends TSchema[] ? TUnionEvaluated : never -// prettier-ignore -type TExcludeResolve = - T extends TTemplateLiteral ? TExcludeTemplateLiteral : - T extends TUnion ? TExcludeArray : - T extends U - ? TNever - : T -// prettier-ignore -function ExcludeResolve(L: L, R: R): TExcludeResolve { - return ( - IsTemplateLiteral(L) ? ExcludeResolve(TemplateLiteralToUnion(L), R) : - IsTemplateLiteral(R) ? ExcludeResolve(L, TemplateLiteralToUnion(R)) : - IsUnion(L) ? (() => { - const narrowed = L.anyOf.filter((inner) => ExtendsCheck(inner, R) === ExtendsResult.False) - return (narrowed.length === 1 ? narrowed[0] : Union(narrowed)) - })() : - ExtendsCheck(L, R) !== ExtendsResult.False ? Never() : - L - ) as TExcludeResolve + +function ExcludeRest(L: [...L], R: R) { + const excluded = L.filter((inner) => ExtendsCheck(inner, R) === ExtendsResult.False) + return excluded.length === 1 ? excluded[0] : Union(excluded) } // ------------------------------------------------------------------ // TExclude // ------------------------------------------------------------------ -export type TExclude = TExcludeResolve - +// prettier-ignore +export type TExclude = ( + L extends TMappedResult ? TExcludeFromMappedResult : + L extends TTemplateLiteral ? TExcludeTemplateLiteral : + L extends TUnion ? TExcludeRest : + L extends R ? TNever : L +) /** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ -export function Exclude(unionType: L, excludedMembers: R, options?: SchemaOptions): TExcludeFromMappedResult -/** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ -export function Exclude(unionType: L, excludedMembers: R, options?: SchemaOptions): TExclude -/** `[Json]` Constructs a type by excluding from unionType all union members that are assignable to excludedMembers */ -export function Exclude(unionType: TSchema, excludedMembers: TSchema, options: SchemaOptions = {}) { - if (IsMappedResult(unionType)) { - return ExcludeFromMappedResult(unionType, excludedMembers, options) - } else { - const E = ExcludeResolve(unionType, excludedMembers) as any - return CloneType(E, options) - } +export function Exclude(L: L, R: R, options: SchemaOptions = {}): TExclude { + // prettier-ignore + return CloneType(( + IsMappedResult(L) ? ExcludeFromMappedResult(L, R, options) : + IsTemplateLiteral(L) ? Exclude(TemplateLiteralToUnion(L), R) : + IsTemplateLiteral(R) ? Exclude(L, TemplateLiteralToUnion(R)) : + IsUnion(L) ? ExcludeRest(L.anyOf, R) : + ExtendsCheck(L, R) !== ExtendsResult.False ? Never() : L + ), options) as never } diff --git a/src/type/extract/extract.ts b/src/type/extract/extract.ts index 7e6dc05..a1f6f4d 100644 --- a/src/type/extract/extract.ts +++ b/src/type/extract/extract.ts @@ -33,7 +33,7 @@ import { TemplateLiteralToUnion, type TTemplateLiteral } from '../template-liter import { type TLiteral } from '../literal/index' import { Union, type TUnion } from '../union/index' import { type Static } from '../static/index' -import { Never } from '../never/index' +import { Never, type TNever } from '../never/index' import { type TUnionEvaluated } from '../union/index' import { ExtendsCheck, ExtendsResult } from '../extends/index' import { CloneType } from '../clone/type' @@ -44,51 +44,42 @@ import { ExtractFromMappedResult, type TExtractFromMappedResult } from './extrac // ------------------------------------------------------------------ import { IsMappedResult, IsTemplateLiteral, IsUnion } from '../guard/type' // ------------------------------------------------------------------ -// ExtractResolve +// ExtractTemplateLiteral // ------------------------------------------------------------------ // prettier-ignore -type TFromTemplateLiteralResult = TUnionEvaluated }[T]>>> +type TExtractTemplateLiteralResult = TUnionEvaluated }[T]>>> // prettier-ignore -type TFromTemplateLiteral = Extract, Static> extends infer S ? TFromTemplateLiteralResult> : never +type TExtractTemplateLiteral = Extract, Static> extends infer S ? TExtractTemplateLiteralResult> : never +// ------------------------------------------------------------------ +// ExtractRest +// ------------------------------------------------------------------ // prettier-ignore -type TFromArray = AssertRest> extends Static ? T[K] : never +type TExtractRest = AssertRest> extends Static ? L[K] : never }[number]>> extends infer R extends TSchema[] ? TUnionEvaluated : never -// prettier-ignore -type TExtractResolve = ( - T extends TTemplateLiteral ? TFromTemplateLiteral : - T extends TUnion ? TFromArray : - T -) -// prettier-ignore -function ExtractResolve(L: L, R: R): TExtractResolve { - return ( - IsTemplateLiteral(L) ? ExtractResolve(TemplateLiteralToUnion(L), R) : - IsTemplateLiteral(R) ? ExtractResolve(L, TemplateLiteralToUnion(R) as any) : - IsUnion(L) ? (() => { - const narrowed = L.anyOf.filter((inner) => ExtendsCheck(inner, R) !== ExtendsResult.False) - return (narrowed.length === 1 ? narrowed[0] : Union(narrowed)) - })() : - ExtendsCheck(L, R) !== ExtendsResult.False ? L : - Never() - ) as TExtractResolve + +function ExtractRest(L: [...L], R: R) { + const extracted = L.filter((inner) => ExtendsCheck(inner, R) !== ExtendsResult.False) + return extracted.length === 1 ? extracted[0] : Union(extracted) } // ------------------------------------------------------------------ // TExtract // ------------------------------------------------------------------ // prettier-ignore -export type TExtract = TExtractResolve - +export type TExtract = ( + L extends TMappedResult ? TExtractFromMappedResult : + L extends TTemplateLiteral ? TExtractTemplateLiteral : + L extends TUnion ? TExtractRest : + L extends U ? L : TNever +) /** `[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): TExtractFromMappedResult -/** `[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(type: TSchema, union: TSchema, options: SchemaOptions = {}) { - if (IsMappedResult(type)) { - return ExtractFromMappedResult(type, union, options) - } else { - const E = ExtractResolve(type, union) - return CloneType(E, options) - } +export function Extract(L: L, R: R, options: SchemaOptions = {}): TExtract { + // prettier-ignore + return CloneType(( + IsMappedResult(L) ? ExtractFromMappedResult(L, R, options) : + IsTemplateLiteral(L) ? Extract(TemplateLiteralToUnion(L), R) : + IsTemplateLiteral(R) ? Extract(L, TemplateLiteralToUnion(R) as any) : + IsUnion(L) ? ExtractRest(L.anyOf, R) : + ExtendsCheck(L, R) !== ExtendsResult.False ? L : Never() + ), options) as never } diff --git a/src/type/indexed/indexed-from-mapped-key.ts b/src/type/indexed/indexed-from-mapped-key.ts index 76dc90e..d32a110 100644 --- a/src/type/indexed/indexed-from-mapped-key.ts +++ b/src/type/indexed/indexed-from-mapped-key.ts @@ -27,7 +27,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ import type { TSchema, SchemaOptions } from '../schema/index' -import type { Evaluate } from '../helpers/index' +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' @@ -90,7 +90,7 @@ export type TIndexFromMappedKey< K extends TMappedKey, P extends TProperties = TMappedIndexProperties > = ( - TMappedResult

+ Ensure> ) // prettier-ignore export function IndexFromMappedKey< diff --git a/src/type/keyof/keyof-from-mapped-result.ts b/src/type/keyof/keyof-from-mapped-result.ts index 8e10c66..d7edcd9 100644 --- a/src/type/keyof/keyof-from-mapped-result.ts +++ b/src/type/keyof/keyof-from-mapped-result.ts @@ -27,6 +27,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ import type { SchemaOptions } from '../schema/index' +import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { KeyOf, type TKeyOf } from './keyof' @@ -55,7 +56,7 @@ function FromProperties< type TFromMappedResult< R extends TMappedResult > = ( - TFromProperties + Evaluate> ) // prettier-ignore function FromMappedResult< @@ -71,7 +72,7 @@ export type TKeyOfFromMappedResult< R extends TMappedResult, P extends TProperties = TFromMappedResult > = ( - TMappedResult

+ Ensure> ) // prettier-ignore export function KeyOfFromMappedResult< diff --git a/src/type/keyof/keyof.ts b/src/type/keyof/keyof.ts index 5fcd4e5..8e3b8fc 100644 --- a/src/type/keyof/keyof.ts +++ b/src/type/keyof/keyof.ts @@ -45,16 +45,16 @@ import { IsMappedResult } from '../guard/type' // FromPropertyKeys // ------------------------------------------------------------------ // prettier-ignore -type TFromPropertyKeys = ( +export type TKeyOfPropertyKeysToRest = ( T extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] ? L extends '[number]' - ? TFromPropertyKeys - : TFromPropertyKeys>]> + ? TKeyOfPropertyKeysToRest + : TKeyOfPropertyKeysToRest>]> : Acc ) // prettier-ignore -function FromPropertyKeys(T: [...T]): TFromPropertyKeys { - return T.map(L => L === '[number]' ? Number() : Literal(L as TLiteralValue)) as TFromPropertyKeys +export function KeyOfPropertyKeysToRest(T: [...T]): TKeyOfPropertyKeysToRest { + return T.map(L => L === '[number]' ? Number() : Literal(L as TLiteralValue)) as TKeyOfPropertyKeysToRest } // ------------------------------------------------------------------ // KeyOfTypeResolve @@ -63,7 +63,7 @@ function FromPropertyKeys(T: [...T]): TFromPropertyKeys export type TKeyOf< T extends TSchema, K extends PropertyKey[] = TKeyOfPropertyKeys, - S extends TSchema[] = TFromPropertyKeys, + S extends TSchema[] = TKeyOfPropertyKeysToRest, U = TUnionEvaluated > = ( Ensure @@ -78,7 +78,7 @@ export function KeyOf(T: TSchema, options: SchemaOptions = {}): any { return KeyOfFromMappedResult(T, options) } else { const K = KeyOfPropertyKeys(T) - const S = FromPropertyKeys(K) + const S = KeyOfPropertyKeysToRest(K) const U = UnionEvaluated(S) return CloneType(U, options) } diff --git a/src/type/mapped/mapped.ts b/src/type/mapped/mapped.ts index 0c6588b..6ab806b 100644 --- a/src/type/mapped/mapped.ts +++ b/src/type/mapped/mapped.ts @@ -241,19 +241,19 @@ function FromSchemaType(K: K, T: T): F ) as FromSchemaType } // ------------------------------------------------------------------ -// FromMappedFunctionReturnType +// MappedFunctionReturnType // ------------------------------------------------------------------ // prettier-ignore -type FromMappedFunctionReturnType = ( +export type TMappedFunctionReturnType = ( K extends [infer L extends PropertyKey, ...infer R extends PropertyKey[]] - ? FromMappedFunctionReturnType }> + ? TMappedFunctionReturnType }> : Acc ) // prettier-ignore -function FromMappedFunctionReturnType(K: [...K], T: T, Acc: TProperties = {}): FromMappedFunctionReturnType { +export function MappedFunctionReturnType(K: [...K], T: T, Acc: TProperties = {}): TMappedFunctionReturnType { return K.reduce((Acc, L) => { return { ...Acc, [L]: FromSchemaType(L, T) } - }, {} as TProperties) as FromMappedFunctionReturnType + }, {} as TProperties) as TMappedFunctionReturnType } // ------------------------------------------------------------------ // TMappedFunction @@ -267,7 +267,7 @@ export type TMappedFunction> = (T: I) export type TMapped< K extends PropertyKey[], F extends TMappedFunction, - R extends TProperties = Evaluate>>, + R extends TProperties = Evaluate>>, > = Ensure> /** `[Json]` Creates a Mapped object type */ @@ -278,6 +278,6 @@ export function Mapped = T 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 = FromMappedFunctionReturnType(K, RT) + const R = MappedFunctionReturnType(K, RT) return CloneType(Object(R), options) } diff --git a/src/type/omit/omit-from-mapped-result.ts b/src/type/omit/omit-from-mapped-result.ts index d08f83f..01327fe 100644 --- a/src/type/omit/omit-from-mapped-result.ts +++ b/src/type/omit/omit-from-mapped-result.ts @@ -27,6 +27,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ import type { SchemaOptions } from '../schema/index' +import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Omit, type TOmit } from './omit' @@ -58,7 +59,7 @@ type TFromMappedResult< R extends TMappedResult, K extends PropertyKey[], > = ( - TFromProperties + Evaluate> ) // prettier-ignore function FromMappedResult< @@ -76,7 +77,7 @@ export type TOmitFromMappedResult< K extends PropertyKey[], P extends TProperties = TFromMappedResult > = ( - TMappedResult

+ Ensure> ) // prettier-ignore export function OmitFromMappedResult< diff --git a/src/type/partial/partial-from-mapped-result.ts b/src/type/partial/partial-from-mapped-result.ts index 2681232..00f7338 100644 --- a/src/type/partial/partial-from-mapped-result.ts +++ b/src/type/partial/partial-from-mapped-result.ts @@ -27,6 +27,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ import type { SchemaOptions } from '../schema/index' +import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Partial, type TPartial } from './partial' @@ -55,7 +56,7 @@ function FromProperties< type TFromMappedResult< R extends TMappedResult > = ( - TFromProperties + Evaluate> ) // prettier-ignore function FromMappedResult< @@ -71,7 +72,7 @@ export type TPartialFromMappedResult< R extends TMappedResult, P extends TProperties = TFromMappedResult > = ( - TMappedResult

+ Ensure> ) // prettier-ignore export function PartialFromMappedResult< diff --git a/src/type/pick/pick-from-mapped-result.ts b/src/type/pick/pick-from-mapped-result.ts index 4238fd3..bfa997a 100644 --- a/src/type/pick/pick-from-mapped-result.ts +++ b/src/type/pick/pick-from-mapped-result.ts @@ -27,6 +27,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ import type { SchemaOptions } from '../schema/index' +import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Pick, type TPick } from './pick' @@ -58,7 +59,7 @@ type TFromMappedResult< R extends TMappedResult, K extends PropertyKey[], > = ( - TFromProperties + Evaluate> ) // prettier-ignore function FromMappedResult< @@ -76,7 +77,7 @@ export type TPickFromMappedResult< K extends PropertyKey[], P extends TProperties = TFromMappedResult > = ( - TMappedResult

+ Ensure> ) // prettier-ignore export function PickFromMappedResult< diff --git a/src/type/pick/pick.ts b/src/type/pick/pick.ts index b746bf1..976cba5 100644 --- a/src/type/pick/pick.ts +++ b/src/type/pick/pick.ts @@ -50,7 +50,7 @@ import { IsMappedKey, IsMappedResult, IsIntersect, IsUnion, IsObject, IsSchema } // prettier-ignore type FromIntersect = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? FromIntersect]> + ? FromIntersect]> : Acc function FromIntersect(T: T, K: K) { return T.map((T) => PickResolve(T, K)) as FromIntersect @@ -61,7 +61,7 @@ function FromIntersect(T: T, K: K) // prettier-ignore type FromUnion = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? FromUnion]> + ? FromUnion]> : Acc // prettier-ignore function FromUnion(T: T, K: K) { @@ -82,25 +82,25 @@ function FromProperties(T: T, K: // PickResolve // ------------------------------------------------------------------ // prettier-ignore -export type PickResolve = - T extends TRecursive ? TRecursive> : +export type TPickResolve = + T extends TRecursive ? TRecursive> : T extends TIntersect ? TIntersect> : T extends TUnion ? TUnion> : T extends TObject ? TObject> : TObject<{}> // prettier-ignore -export function PickResolve(T: T, K: [...K]): PickResolve { +export function PickResolve(T: T, K: [...K]): TPickResolve { return ( IsIntersect(T) ? Intersect(FromIntersect(T.allOf, K)) : IsUnion(T) ? Union(FromUnion(T.anyOf, K)) : IsObject(T) ? Object(FromProperties(T.properties, K)) : Object({}) - ) as PickResolve + ) as TPickResolve } // ------------------------------------------------------------------ // TPick // ------------------------------------------------------------------ -export type TPick = PickResolve +export type TPick = TPickResolve /** `[Json]` Constructs a type whose keys are picked from the given type */ export function Pick(T: T, K: [...K], options?: SchemaOptions): TPickFromMappedResult diff --git a/src/type/required/required-from-mapped-result.ts b/src/type/required/required-from-mapped-result.ts index b73554f..bcf5780 100644 --- a/src/type/required/required-from-mapped-result.ts +++ b/src/type/required/required-from-mapped-result.ts @@ -27,6 +27,7 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ import type { SchemaOptions } from '../schema/index' +import type { Ensure, Evaluate } from '../helpers/index' import type { TProperties } from '../object/index' import { MappedResult, type TMappedResult } from '../mapped/index' import { Required, type TRequired } from './required' @@ -55,7 +56,7 @@ function FromProperties< type TFromMappedResult< R extends TMappedResult > = ( - TFromProperties + Evaluate> ) // prettier-ignore function FromMappedResult< @@ -71,7 +72,7 @@ export type TRequiredFromMappedResult< R extends TMappedResult, P extends TProperties = TFromMappedResult > = ( - TMappedResult

+ Ensure> ) // prettier-ignore export function RequiredFromMappedResult< diff --git a/src/type/static/static.ts b/src/type/static/static.ts index 25a9083..488055c 100644 --- a/src/type/static/static.ts +++ b/src/type/static/static.ts @@ -52,41 +52,41 @@ import type { TTransform } from '../transform/index' // DecodeType // ------------------------------------------------------------------ // prettier-ignore -export type DecodeProperties = { - [K in keyof T]: DecodeType +export type TDecodeProperties = { + [K in keyof T]: TDecodeType } // prettier-ignore -export type DecodeRest = +export type TDecodeRest = T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? DecodeRest]> + ? TDecodeRest]> : Acc // prettier-ignore -export type DecodeType = ( - T extends TOptional ? TOptional> : - T extends TReadonly ? TReadonly> : +export type TDecodeType = ( + T extends TOptional ? TOptional> : + T extends TReadonly ? TReadonly> : T extends TTransform ? TUnsafe : - T extends TArray ? TArray> : - T extends TAsyncIterator ? TAsyncIterator> : - T extends TConstructor ? TConstructor, DecodeType> : + T extends TArray ? TArray> : + T extends TAsyncIterator ? TAsyncIterator> : + T extends TConstructor ? TConstructor, TDecodeType> : T extends TEnum ? TEnum : // intercept for union. interior non decodable - T extends TFunction ? TFunction, DecodeType> : - T extends TIntersect ? TIntersect> : - T extends TIterator ? TIterator> : - T extends TNot ? TNot> : - T extends TObject ? TObject>> : - T extends TPromise ? TPromise> : - T extends TRecord ? TRecord> : - T extends TRecursive ? TRecursive> : - T extends TRef ? TRef> : - T extends TTuple ? TTuple> : - T extends TUnion ? TUnion> : + T extends TFunction ? TFunction, TDecodeType> : + T extends TIntersect ? TIntersect> : + T extends TIterator ? TIterator> : + T extends TNot ? TNot> : + T extends TObject ? TObject>> : + T extends TPromise ? TPromise> : + T extends TRecord ? TRecord> : + T extends TRecursive ? TRecursive> : + T extends TRef ? TRef> : + T extends TTuple ? TTuple> : + T extends TUnion ? TUnion> : T ) // ------------------------------------------------------------------ // Static // ------------------------------------------------------------------ /** Creates an decoded static type from a TypeBox type */ -export type StaticDecode = Static, P> +export type StaticDecode = Static, P> /** Creates an encoded static type from a TypeBox type */ export type StaticEncode = Static /** Creates a static type from a TypeBox type */ diff --git a/test/runtime/type/guard/exclude.ts b/test/runtime/type/guard/exclude.ts index 78fbdfe..8836667 100644 --- a/test/runtime/type/guard/exclude.ts +++ b/test/runtime/type/guard/exclude.ts @@ -3,40 +3,40 @@ import { Type } from '@sinclair/typebox' import { Assert } from '../../assert/index' describe('type/guard/TExclude', () => { - it('Should extract string from number', () => { + it('Should exclude string from number', () => { const T = Type.Exclude(Type.String(), Type.Number()) Assert.IsTrue(TypeGuard.IsString(T)) }) - it('Should extract string from string', () => { + it('Should exclude string from string', () => { const T = Type.Exclude(Type.String(), Type.String()) Assert.IsTrue(TypeGuard.IsNever(T)) }) - it('Should extract string | number | boolean from string', () => { + it('Should exclude string | number | boolean from string', () => { const T = Type.Exclude(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.String()) Assert.IsTrue(TypeGuard.IsUnion(T)) Assert.IsTrue(TypeGuard.IsNumber(T.anyOf[0])) Assert.IsTrue(TypeGuard.IsBoolean(T.anyOf[1])) }) - it('Should extract string | number | boolean from string | boolean', () => { + it('Should exclude string | number | boolean from string | boolean', () => { const T = Type.Exclude(Type.Union([Type.String(), Type.Number(), Type.Boolean()]), Type.Union([Type.String(), Type.Boolean()])) Assert.IsTrue(TypeGuard.IsNumber(T)) }) // ------------------------------------------------------------------------ // TemplateLiteral | TemplateLiteral // ------------------------------------------------------------------------ - it('Should extract TemplateLiteral | TemplateLiteral 1', () => { + it('Should exclude TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Exclude(A, B) Assert.IsTrue(TypeGuard.IsNever(T)) }) - it('Should extract TemplateLiteral | TemplateLiteral 1', () => { + it('Should exclude TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C'].includes(T.const)) }) - it('Should extract TemplateLiteral | TemplateLiteral 1', () => { + it('Should exclude TemplateLiteral | TemplateLiteral 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Exclude(A, B) @@ -46,19 +46,19 @@ describe('type/guard/TExclude', () => { // ------------------------------------------------------------------------ // TemplateLiteral | Union 1 // ------------------------------------------------------------------------ - it('Should extract TemplateLiteral | Union 1', () => { + it('Should exclude TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const T = Type.Exclude(A, B) Assert.IsTrue(TypeGuard.IsNever(T)) }) - it('Should extract TemplateLiteral | Union 1', () => { + it('Should exclude TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A'), Type.Literal('B')]) const T = Type.Exclude(A, B) Assert.IsTrue(['C'].includes(T.const)) }) - it('Should extract TemplateLiteral | Union 1', () => { + it('Should exclude TemplateLiteral | Union 1', () => { const A = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const B = Type.Union([Type.Literal('A')]) const T = Type.Exclude(A, B) @@ -68,23 +68,29 @@ describe('type/guard/TExclude', () => { // ------------------------------------------------------------------------ // Union | TemplateLiteral 1 // ------------------------------------------------------------------------ - it('Should extract Union | TemplateLiteral 1', () => { + it('Should exclude Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')])]) const T = Type.Exclude(A, B) Assert.IsTrue(TypeGuard.IsNever(T)) }) - it('Should extract Union | TemplateLiteral 1', () => { + it('Should exclude Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A'), Type.Literal('B')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C'].includes(T.const)) }) - it('Should extract Union | TemplateLiteral 1', () => { + it('Should exclude Union | TemplateLiteral 1', () => { const A = Type.Union([Type.Literal('A'), Type.Literal('B'), Type.Literal('C')]) const B = Type.TemplateLiteral([Type.Union([Type.Literal('A')])]) const T = Type.Exclude(A, B) Assert.IsTrue(['C', 'B'].includes(T.anyOf[0].const)) Assert.IsTrue(['C', 'B'].includes(T.anyOf[1].const)) }) + it('Should exclude with options', () => { + const A = Type.String() + const B = Type.String() + const T = Type.Exclude(A, B, { foo: 'bar' }) + Assert.IsEqual(T.foo, 'bar') + }) }) diff --git a/test/runtime/type/guard/extract.ts b/test/runtime/type/guard/extract.ts index b3524d1..ffa7d88 100644 --- a/test/runtime/type/guard/extract.ts +++ b/test/runtime/type/guard/extract.ts @@ -93,4 +93,10 @@ describe('type/guard/TExtract', () => { const T = Type.Extract(A, B) Assert.IsTrue(['A'].includes(T.const)) }) + it('Should extract with options', () => { + const A = Type.String() + const B = Type.String() + const T = Type.Extract(A, B, { foo: 'bar' }) + Assert.IsEqual(T.foo, 'bar') + }) }) diff --git a/test/static/extract.ts b/test/static/extract.ts index 4bd3dc8..0ed6a2a 100644 --- a/test/static/extract.ts +++ b/test/static/extract.ts @@ -7,7 +7,7 @@ import { Expect } from './assert' } { const T = Type.Extract(Type.String(), Type.Number()) - Expect(T).ToStatic() + Expect(T).ToStaticNever() } { const T = Type.Extract(Type.Union([Type.Number(), Type.String(), Type.Boolean()]), Type.Number())