From 39765414b4316a1e9630f238173d5e36b865d843 Mon Sep 17 00:00:00 2001 From: Haydn Paterson Date: Wed, 4 Dec 2024 17:18:00 +0900 Subject: [PATCH] Revision 0.34.10 (#1107) * Add Remote Build Task * Use Overloads for Index Signature * Tidy Record Module Inference * Add Encode to Parse Operation Type * Fix Record Key mapping when using Import * Version * ChangeLog --- changelog/0.34.0.md | 5 + hammer.mjs | 25 ++ package-lock.json | 4 +- package.json | 3 +- src/type/indexed/indexed-from-mapped-key.ts | 11 +- .../indexed/indexed-from-mapped-result.ts | 3 +- src/type/indexed/indexed-property-keys.ts | 26 +-- src/type/indexed/indexed.ts | 218 ++++++++---------- src/type/module/compute.ts | 18 +- src/type/module/infer.ts | 2 +- src/type/record/record.ts | 6 +- src/type/type/json.ts | 16 +- src/value/parse/parse.ts | 2 +- 13 files changed, 176 insertions(+), 163 deletions(-) diff --git a/changelog/0.34.0.md b/changelog/0.34.0.md index 7e5e4693..0b821e45 100644 --- a/changelog/0.34.0.md +++ b/changelog/0.34.0.md @@ -1,4 +1,9 @@ ### 0.34.0 +- [Revision 0.34.10](https://github.com/sinclairzx81/typebox/pull/1107) + - Fix Declaration Emit for Index and Mapped Types + - Fix Record Inference Presentation when Embedded in Modules + - Fix Record Mapping when using TImport as Key + - Add Encode to Parse Operation List - [Revision 0.34.9](https://github.com/sinclairzx81/typebox/pull/1101) - User Defined Parse Pipelines - Access to Schema and References on TypeCheck diff --git a/hammer.mjs b/hammer.mjs index 02dacedf..26f75800 100644 --- a/hammer.mjs +++ b/hammer.mjs @@ -9,12 +9,14 @@ export async function clean() { await folder('node_modules/typebox').delete() await folder('target').delete() } + // ------------------------------------------------------------------------------- // Format // ------------------------------------------------------------------------------- export async function format() { await shell('prettier --no-semi --single-quote --print-width 240 --trailing-comma all --write src test task example/index.ts') } + // ------------------------------------------------------------------------------- // Start // ------------------------------------------------------------------------------- @@ -28,6 +30,7 @@ export async function benchmark() { await Benchmark.compression() await Benchmark.measurement() } + // ------------------------------------------------------------------------------- // Test // ------------------------------------------------------------------------------- @@ -49,6 +52,7 @@ export async function test(filter = '') { await test_static() await test_runtime(filter) } + // ------------------------------------------------------------------------------- // Build // ------------------------------------------------------------------------------- @@ -69,6 +73,25 @@ export async function build(target = 'target/build') { await shell(`cd ${target} && npm pack`) await build_check(target) } + +// ------------------------------------------------------------------------------- +// Build To +// ------------------------------------------------------------------------------- +export async function build_to(remote = 'target/remote', target = 'target/build') { + await clean() + await Promise.all([ + Build.Package.build(target), + Build.Esm.build(target), + Build.Cjs.build(target), + ]) + await folder(target).add('readme.md') + await folder(target).add('license') + await shell(`cd ${target} && npm pack`) + const { version } = JSON.parse(Fs.readFileSync('package.json', 'utf8')) + const filename = `${target}/sinclair-typebox-${version}.tgz` + await folder(remote).add(filename) +} + // ------------------------------------------------------------------------------- // Install // ------------------------------------------------------------------------------- @@ -77,6 +100,7 @@ export async function install_local() { await build('target/typebox') await folder('node_modules').add('target/typebox') } + // ------------------------------------------------------------- // Publish // ------------------------------------------------------------- @@ -87,6 +111,7 @@ export async function publish(otp, target = 'target/build') { await shell(`git tag ${version}`) await shell(`git push origin ${version}`) } + // ------------------------------------------------------------- // Publish-Dev // ------------------------------------------------------------- diff --git a/package-lock.json b/package-lock.json index a962edf2..acfa4550 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sinclair/typebox", - "version": "0.34.9", + "version": "0.34.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@sinclair/typebox", - "version": "0.34.9", + "version": "0.34.10", "license": "MIT", "devDependencies": { "@arethetypeswrong/cli": "^0.13.2", diff --git a/package.json b/package.json index 279b3dd5..8b857c36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sinclair/typebox", - "version": "0.34.9", + "version": "0.34.10", "description": "Json Schema Type Builder with Static Type Resolution for TypeScript", "keywords": [ "typescript", @@ -20,6 +20,7 @@ "test:runtime": "hammer task test_runtime", "install:local": "hammer task install_local", "benchmark": "hammer task benchmark", + "build:to": "hammer task build_to", "build": "hammer task build", "test": "hammer task test", "clean": "hammer task clean", diff --git a/src/type/indexed/indexed-from-mapped-key.ts b/src/type/indexed/indexed-from-mapped-key.ts index b66cf511..a523032f 100644 --- a/src/type/indexed/indexed-from-mapped-key.ts +++ b/src/type/indexed/indexed-from-mapped-key.ts @@ -41,8 +41,7 @@ type TMappedIndexPropertyKey = { [_ in Key]: TIndex } // prettier-ignore -function MappedIndexPropertyKey(type: Type, key: Key, options?: SchemaOptions): TMappedIndexPropertyKey { +function MappedIndexPropertyKey(type: Type, key: Key, options?: SchemaOptions): TMappedIndexPropertyKey { return { [key]: Index(type, [key], Clone(options)) } as never } // ------------------------------------------------------------------ @@ -55,7 +54,10 @@ type TMappedIndexPropertyKeys(type: Type, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TMappedIndexPropertyKeys { +function MappedIndexPropertyKeys< + Type extends TSchema, + PropertyKeys extends PropertyKey[] +>(type: Type, propertyKeys: [...PropertyKeys], options?: SchemaOptions): TMappedIndexPropertyKeys { return propertyKeys.reduce((result, left) => { return { ...result, ...MappedIndexPropertyKey(type, left, options) } }, {} as TProperties) as never @@ -68,7 +70,8 @@ type TMappedIndexProperties TMappedIndexPropertyKeys > // prettier-ignore -function MappedIndexProperties(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TMappedIndexProperties { +function MappedIndexProperties(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TMappedIndexProperties { return MappedIndexPropertyKeys(type, mappedKey.keys, options) as never } // ------------------------------------------------------------------ diff --git a/src/type/indexed/indexed-from-mapped-result.ts b/src/type/indexed/indexed-from-mapped-result.ts index e2b2b007..20049364 100644 --- a/src/type/indexed/indexed-from-mapped-result.ts +++ b/src/type/indexed/indexed-from-mapped-result.ts @@ -43,8 +43,7 @@ type TFromProperties = ( function FromProperties(type: Type, properties: Properties, options?: SchemaOptions): TFromProperties { const result = {} as Record for(const K2 of Object.getOwnPropertyNames(properties)) { - const keys = IndexPropertyKeys(properties[K2]) - result[K2] = Index(type, keys, options) as never + result[K2] = Index(type, IndexPropertyKeys(properties[K2]), options) } return result as never } diff --git a/src/type/indexed/indexed-property-keys.ts b/src/type/indexed/indexed-property-keys.ts index ad73541e..d5f2e731 100644 --- a/src/type/indexed/indexed-property-keys.ts +++ b/src/type/indexed/indexed-property-keys.ts @@ -41,13 +41,11 @@ import { IsTemplateLiteral, IsUnion, IsLiteral, IsNumber, IsInteger } from '../g // FromTemplateLiteral // ------------------------------------------------------------------ // prettier-ignore -type TFromTemplateLiteral -> = Result +type TFromTemplateLiteral> = (Keys) // prettier-ignore function FromTemplateLiteral(templateLiteral: TemplateLiteral): TFromTemplateLiteral { - const result = TemplateLiteralGenerate(templateLiteral) as string[] - return result.map(S => S.toString()) as never + const keys = TemplateLiteralGenerate(templateLiteral) as string[] + return keys.map(key => key.toString()) as never } // ------------------------------------------------------------------ // FromUnion @@ -59,9 +57,9 @@ type TFromUnion = ( : Result ) // prettier-ignore -function FromUnion(type: Type): TFromUnion { +function FromUnion(types: Types): TFromUnion { const result = [] as string[] - for(const left of type) result.push(...IndexPropertyKeys(left)) + for(const type of types) result.push(...IndexPropertyKeys(type)) return result as never } // ------------------------------------------------------------------ @@ -74,23 +72,23 @@ type TFromLiteral = ( : [] ) // prettier-ignore -function FromLiteral(T: LiteralValue): TFromLiteral { +function FromLiteral(literalValue: LiteralValue): TFromLiteral { return ( - [(T as string).toString()] // TS 5.4 observes TLiteralValue as not having a toString() + [(literalValue as string).toString()] // TS 5.4 observes TLiteralValue as not having a toString() ) as never } // ------------------------------------------------------------------ -// IndexedKeyResolve +// IndexPropertyKeys // ------------------------------------------------------------------ // prettier-ignore -export type TIndexPropertyKeys : +export type TIndexPropertyKeys = ( + Type extends TTemplateLiteral ? TFromTemplateLiteral : Type extends TUnion ? TFromUnion : - Type extends TLiteral ? TFromLiteral : + Type extends TLiteral ? TFromLiteral : Type extends TNumber ? ['[number]'] : Type extends TInteger ? ['[number]'] : [] -)> = Result +) /** Returns a tuple of PropertyKeys derived from the given TSchema */ // prettier-ignore export function IndexPropertyKeys(type: Type): TIndexPropertyKeys { diff --git a/src/type/indexed/indexed.ts b/src/type/indexed/indexed.ts index 5598b034..541c6e73 100644 --- a/src/type/indexed/indexed.ts +++ b/src/type/indexed/indexed.ts @@ -27,70 +27,45 @@ THE SOFTWARE. ---------------------------------------------------------------------------*/ import { CreateType } from '../create/type' +import { TypeBoxError } from '../error/index' + import { type TSchema, SchemaOptions } from '../schema/index' -import { Computed, type TComputed } from '../computed/index' -import { Literal, type TLiteral, type TLiteralValue } from '../literal/index' +import { type Assert } from '../helpers/index' +import { type TComputed, Computed } from '../computed/index' +import { type TNever, Never } from '../never/index' +import { type TArray } from '../array/index' +import { type TIntersect } from '../intersect/index' +import { type TMappedResult, type TMappedKey } from '../mapped/index' import { type TObject, type TProperties } from '../object/index' -import { type Ensure, type Assert } from '../helpers/index' -import { Never, type TNever } from '../never/index' +import { type TUnion } from '../union/index' import { type TRecursive } from '../recursive/index' -import { type TIntersect } from '../intersect/index' -import { TMappedResult, type TMappedKey } from '../mapped/index' -import { Union, type TUnion } from '../union/index' +import { type TRef } from '../ref/index' import { type TTuple } from '../tuple/index' -import { type TArray } from '../array/index' -import { Ref, type TRef } from '../ref/index' + import { IntersectEvaluated, type TIntersectEvaluated } from '../intersect/index' import { UnionEvaluated, type TUnionEvaluated } from '../union/index' -// ------------------------------------------------------------------ -// Infrastructure -// ------------------------------------------------------------------ import { IndexPropertyKeys, type TIndexPropertyKeys } from './indexed-property-keys' import { IndexFromMappedKey, type TIndexFromMappedKey } from './indexed-from-mapped-key' import { IndexFromMappedResult, type TIndexFromMappedResult } from './indexed-from-mapped-result' // ------------------------------------------------------------------ -// KindGuard +// TypeGuard // ------------------------------------------------------------------ -import { IsArray, IsIntersect, IsObject, IsMappedKey, IsMappedResult, IsNever, IsSchema, IsTuple, IsUnion, IsLiteralValue, IsRef, IsComputed } from '../guard/kind' -import { IsArray as IsArrayValue } from '../guard/value' - -// ------------------------------------------------------------------ -// FromComputed -// ------------------------------------------------------------------ -// prettier-ignore -// type TFromComputed = Ensure< -// TComputed<'Partial', [TComputed]> -// > -// // prettier-ignore -// function FromComputed(target: Target, parameters: Parameters): TFromComputed { -// return Computed('Partial', [Computed(target, parameters)]) as never -// } -// // ------------------------------------------------------------------ -// // FromRef -// // ------------------------------------------------------------------ -// // prettier-ignore -// type TFromRef = Ensure< -// TComputed<'Partial', [TRef]> -// > -// // prettier-ignore -// function FromRef($ref: Ref): TFromRef { -// return Computed('Partial', [Ref($ref)]) as never -// } +import { IsArray, IsIntersect, IsObject, IsMappedKey, IsMappedResult, IsNever, IsSchema, IsTuple, IsUnion, IsRef } from '../guard/kind' // ------------------------------------------------------------------ // FromRest // ------------------------------------------------------------------ // prettier-ignore -type TFromRest = ( - T extends [infer L extends TSchema, ...infer R extends TSchema[]] - ? TFromRest, TSchema>]> +type TFromRest = ( + Types extends [infer Left extends TSchema, ...infer Right extends TSchema[]] + ? TFromRest, TSchema>]> : Result ) // prettier-ignore -function FromRest(types: [...Types], key: K): TFromRest { - return types.map(left => IndexFromPropertyKey(left, key)) as never +function FromRest(types: [...Types], key: Key): TFromRest { + return types.map(type => IndexFromPropertyKey(type, key)) as never } // ------------------------------------------------------------------ // FromIntersectRest @@ -105,7 +80,7 @@ type TFromIntersectRest ) // prettier-ignore function FromIntersectRest(types: [...Types]): TFromIntersectRest { - return types.filter(left => !IsNever(left)) as never + return types.filter(type => !IsNever(type)) as never } // prettier-ignore type TFromIntersect = ( @@ -171,21 +146,17 @@ function FromUnion(types: [... // ------------------------------------------------------------------ // FromTuple // ------------------------------------------------------------------ - // prettier-ignore -type TFromTuple : - Key extends keyof Types - ? Types[Key] extends infer Type extends TSchema - ? Type - : TNever - : TNever -)> = Result +type TFromTuple = ( + Key extends keyof Types ? Types[Key] : + Key extends '[number]' ? TUnionEvaluated : + TNever +) // prettier-ignore function FromTuple(types: [...Types], key: Key): TFromTuple { return ( - key === '[number]' ? UnionEvaluated(types) : key in types ? types[key as number] : + key === '[number]' ? UnionEvaluated(types) : Never() ) as never } @@ -194,20 +165,25 @@ function FromTuple(types: [... // ------------------------------------------------------------------ // prettier-ignore type TFromArray = ( - Key extends '[number]' ? Type : TNever + Key extends '[number]' + ? Type + : TNever ) // prettier-ignore -function FromArray(type: Type, key: Key): TFromArray { - // ... ? - return (key === '[number]' ? type : Never()) as never +function FromArray(type: Type, key: Key): TFromArray { + return ( + key === '[number]' + ? type + : Never() + ) as never } // ------------------------------------------------------------------ // FromProperty // ------------------------------------------------------------------ -type AssertPropertyKey = Assert +type AssertPropertyKey = Assert // prettier-ignore -type TFromProperty = ( // evaluate for string keys Key extends keyof Properties ? Properties[Key] @@ -215,32 +191,32 @@ type TFromProperty}` extends `${AssertPropertyKey}` ? Properties[AssertPropertyKey] : TNever -)> = Result +) // prettier-ignore -function FromProperty(properties: Properties, key: Key): TFromProperty { - return (key in properties ? properties[key as string] : Never()) as never +function FromProperty(properties: Properties, propertyKey: Key): TFromProperty { + return (propertyKey in properties ? properties[propertyKey as string] : Never()) as never } // ------------------------------------------------------------------ // FromKey // ------------------------------------------------------------------ // prettier-ignore export type TIndexFromPropertyKey = ( - Type extends TRecursive ? TIndexFromPropertyKey : - Type extends TIntersect ? TFromIntersect : - Type extends TUnion ? TFromUnion : - Type extends TTuple ? TFromTuple : - Type extends TArray ? TFromArray : - Type extends TObject ? TFromProperty : + Type extends TRecursive ? TIndexFromPropertyKey : + Type extends TIntersect ? TFromIntersect : + Type extends TUnion ? TFromUnion : + Type extends TTuple ? TFromTuple : + Type extends TArray ? TFromArray : + Type extends TObject ? TFromProperty : TNever ) // prettier-ignore -export function IndexFromPropertyKey(type: Type, key: Key): TIndexFromPropertyKey { +export function IndexFromPropertyKey(type: Type, propertyKey: Key): TIndexFromPropertyKey { return ( - IsIntersect(type) ? FromIntersect(type.allOf, key) : - IsUnion(type) ? FromUnion(type.anyOf, key) : - IsTuple(type) ? FromTuple(type.items ?? [], key) : - IsArray(type) ? FromArray(type.items, key) : - IsObject(type) ? FromProperty(type.properties, key) : + IsIntersect(type) ? FromIntersect(type.allOf, propertyKey) : + IsUnion(type) ? FromUnion(type.anyOf, propertyKey) : + IsTuple(type) ? FromTuple(type.items ?? [], propertyKey) : + IsArray(type) ? FromArray(type.items, propertyKey) : + IsObject(type) ? FromProperty(type.properties, propertyKey) : Never() ) as never } @@ -255,76 +231,70 @@ export type TIndexFromPropertyKeys(type: Type, propertyKeys: [...PropertyKeys]): TIndexFromPropertyKeys { - return propertyKeys.map(left => IndexFromPropertyKey(type, left)) as never + return propertyKeys.map(propertyKey => IndexFromPropertyKey(type, propertyKey)) as never } // ------------------------------------------------------------------ // FromSchema // ------------------------------------------------------------------ // prettier-ignore -type TFromType, -> = TUnionEvaluated +type FromSchema = ( + TUnionEvaluated> +) // prettier-ignore -function FromType(type: Type, propertyKeys: [...PropertyKeys]): TFromType { - const result = IndexFromPropertyKeys(type, propertyKeys as PropertyKey[]) - return UnionEvaluated(result) as never +function FromSchema(type: Type, propertyKeys: [...PropertyKeys]): FromSchema { + return ( + UnionEvaluated(IndexFromPropertyKeys(type, propertyKeys as PropertyKey[])) + ) as never } // ------------------------------------------------------------------ -// UnionFromPropertyKeys +// FromSchema // ------------------------------------------------------------------ // prettier-ignore -type TUnionFromPropertyKeys = ( - PropertyKeys extends [infer Key extends PropertyKey, ...infer Rest extends PropertyKey[]] - ? Key extends TLiteralValue - ? TUnionFromPropertyKeys]> - : TUnionFromPropertyKeys - : TUnionEvaluated +export type TIndexFromComputed = ( + TComputed<'Index', [Type, Key]> ) // prettier-ignore -function UnionFromPropertyKeys(propertyKeys: PropertyKeys): TUnionFromPropertyKeys { - const result = propertyKeys.reduce((result, key) => IsLiteralValue(key) ? [...result, Literal(key)]: result, [] as TLiteral[]) - return UnionEvaluated(result) as never +export function IndexFromComputed(type: Type, key: Key): TIndexFromComputed { + return Computed('Index', [type, key]) } // ------------------------------------------------------------------ // TIndex // ------------------------------------------------------------------ -// prettier-ignore (do not export this type) -type TResolvePropertyKeys = Key extends TSchema ? TIndexPropertyKeys : Key -// prettier-ignore (do not export this type) -type TResolveTypeKey = Key extends PropertyKey[] ? TUnionFromPropertyKeys : Key // prettier-ignore -export type TIndex = ( - Key extends TMappedResult ? TIndexFromMappedResult : - Key extends TMappedKey ? TIndexFromMappedKey : - [IsTypeRef, IsKeyRef] extends [true, true] ? TComputed<'Index', [Type, TResolveTypeKey]> : - [IsTypeRef, IsKeyRef] extends [false, true] ? TComputed<'Index', [Type, TResolveTypeKey]> : - [IsTypeRef, IsKeyRef] extends [true, false] ? TComputed<'Index', [Type, TResolveTypeKey]> : - TFromType> +export type TIndex = ( + FromSchema ) /** `[Json]` Returns an Indexed property type for the given keys */ -export function Index(type: Type, key: readonly [...Key], options?: SchemaOptions): TIndex +export function Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ -export function Index(type: Type, key: Key, options?: SchemaOptions): TIndex +export function Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ -export function Index(type: Type, key: Key, options?: SchemaOptions): TIndex +export function Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ -export function Index(type: Type, key: Key, options?: SchemaOptions): TIndex +export function Index(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TIndexFromMappedResult /** `[Json]` Returns an Indexed property type for the given keys */ -// prettier-ignore -export function Index(type: any, key: any, options?: SchemaOptions): any { - const typeKey: TSchema = IsArrayValue(key) ? UnionFromPropertyKeys(key as PropertyKey[]) : key - const propertyKeys: PropertyKey[] = IsSchema(key) ? IndexPropertyKeys(key) : key - const isTypeRef: boolean = IsRef(type) - const isKeyRef: boolean = IsRef(key) - return ( - IsMappedResult(key) ? IndexFromMappedResult(type, key, options) : - IsMappedKey(key) ? IndexFromMappedKey(type, key, options) : - (isTypeRef && isKeyRef) ? Computed('Index', [type, typeKey], options) : - (!isTypeRef && isKeyRef) ? Computed('Index', [type, typeKey], options) : - (isTypeRef && !isKeyRef) ? Computed('Index', [type, typeKey], options) : - CreateType(FromType(type, propertyKeys), options) - ) as never +export function Index(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TIndexFromMappedResult +/** `[Json]` Returns an Indexed property type for the given keys */ +export function Index(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TIndexFromMappedKey +/** `[Json]` Returns an Indexed property type for the given keys */ +export function Index>(T: Type, K: Key, options?: SchemaOptions): TIndex +/** `[Json]` Returns an Indexed property type for the given keys */ +export function Index(type: Type, propertyKeys: readonly [...PropertyKeys], options?: SchemaOptions): TIndex +/** `[Json]` Returns an Indexed property type for the given keys */ +export function Index(type: TSchema, key: any, options?: SchemaOptions): any { + // computed-type + if (IsRef(type) || IsRef(key)) { + const error = `Index types using Ref parameters require both Type and Key to be of TSchema` + if (!IsSchema(type) || !IsSchema(key)) throw new TypeBoxError(error) + return Computed('Index', [type, key]) + } + // mapped-types + if (IsMappedResult(key)) return IndexFromMappedResult(type, key, options) + if (IsMappedKey(key)) return IndexFromMappedKey(type, key, options) + // prettier-ignore + return CreateType( + IsSchema(key) + ? FromSchema(type, IndexPropertyKeys(key)) + : FromSchema(type, key as string[]) + , options) as never } diff --git a/src/type/module/compute.ts b/src/type/module/compute.ts index b2ee6e78..8527ab13 100644 --- a/src/type/module/compute.ts +++ b/src/type/module/compute.ts @@ -35,8 +35,8 @@ import { Awaited, type TAwaited } from '../awaited/index' import { AsyncIterator, type TAsyncIterator } from '../async-iterator/index' import { TComputed } from '../computed/index' import { Constructor, type TConstructor } from '../constructor/index' -import { Index, type TIndex } from '../indexed/index' -import { TEnum, TEnumRecord } from '../enum/index' +import { Index, type TIndex, type TIndexPropertyKeys } from '../indexed/index' +import { TEnum, type TEnumRecord } from '../enum/index' import { Function as FunctionType, type TFunction } from '../function/index' import { Intersect, type TIntersect, type TIntersectEvaluated } from '../intersect/index' import { Iterator, type TIterator } from '../iterator/index' @@ -119,7 +119,14 @@ function FromAwaited(parameters: Parameters): TFro // ------------------------------------------------------------------ // prettier-ignore type TFromIndex = ( - Parameters extends [infer T0 extends TSchema, infer T1 extends TSchema] ? TIndex : never + Parameters extends [infer T0 extends TSchema, infer T1 extends TSchema] + // Note: This inferred result check is required to mitgate a "as never" + // assertion on FromComputed resolution. This should be removed when + // reimplementing TIndex to use TSchema as the primary key indexer. + ? TIndex> extends infer Result extends TSchema + ? Result + : never + : never ) // prettier-ignore function FromIndex(parameters: Parameters): TFromIndex { @@ -370,10 +377,7 @@ export function FromType extends infer Key extends PropertyKey ? Key : never, InferedType extends unknown = TInfer, -> = Record +> = Ensure<{ [_ in InferredKey]: InferedType }> // ------------------------------------------------------------------ // Ref // ------------------------------------------------------------------ diff --git a/src/type/record/record.ts b/src/type/record/record.ts index 78226964..8e7da825 100644 --- a/src/type/record/record.ts +++ b/src/type/record/record.ts @@ -204,7 +204,9 @@ function FromNumberKey(_: Key, type: // ------------------------------------------------------------------ // prettier-ignore type RecordStatic = ( - Evaluate<{ [_ in Assert, PropertyKey>]: Static; }> + // Note: We would return a Record here, but recursive Record types will + // break when T is self recursive. We can mitigate this by using a Mapped instead. + Evaluate<{ [_ in Assert, PropertyKey>]: Static }> ) // prettier-ignore export interface TRecord extends TSchema { @@ -232,7 +234,7 @@ export type TRecordOrObject = ( Key extends TString ? TFromStringKey : Key extends TAny ? TFromAnyKey : Key extends TNever ? TFromNeverKey : - Key + TNever ) // ------------------------------------------------------------------ // TRecordOrObject diff --git a/src/type/type/json.ts b/src/type/type/json.ts index f7efb99c..8cbb88ef 100644 --- a/src/type/type/json.ts +++ b/src/type/type/json.ts @@ -35,7 +35,7 @@ import { Enum, type TEnum, type TEnumKey, type TEnumValue } from '../enum/index' import { Exclude, type TExclude, type TExcludeFromMappedResult, type TExcludeFromTemplateLiteral } from '../exclude/index' import { Extends, type TExtends, type TExtendsFromMappedKey, type TExtendsFromMappedResult } from '../extends/index' import { Extract, type TExtract, type TExtractFromMappedResult, type TExtractFromTemplateLiteral } from '../extract/index' -import { Index, TIndex, type TIndexPropertyKeys, type TIndexFromMappedKey, type TIndexFromMappedResult } from '../indexed/index' +import { Index, TIndex, type TIndexPropertyKeys, type TIndexFromMappedKey, type TIndexFromMappedResult, type TIndexFromComputed } from '../indexed/index' import { Integer, type IntegerOptions, type TInteger } from '../integer/index' import { Intersect, type IntersectOptions } from '../intersect/index' import { Capitalize, Uncapitalize, Lowercase, Uppercase, type TCapitalize, type TUncapitalize, type TLowercase, type TUppercase } from '../intrinsic/index' @@ -164,13 +164,19 @@ export class JsonTypeBuilder { return Extract(type, union, options) } /** `[Json]` Returns an Indexed property type for the given keys */ - public Index(type: Type, key: readonly [...PropertyKeys], options?: SchemaOptions): TIndex + public Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ - public Index(type: Type, key: Key, options?: SchemaOptions): TIndex + public Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ - public Index(type: Type, key: Key, options?: SchemaOptions): TIndex + public Index(type: Type, key: Key, options?: SchemaOptions): TIndexFromComputed /** `[Json]` Returns an Indexed property type for the given keys */ - public Index(type: Type, key: Key, options?: SchemaOptions): TIndex + public Index(type: Type, mappedResult: MappedResult, options?: SchemaOptions): TIndexFromMappedResult + /** `[Json]` Returns an Indexed property type for the given keys */ + public Index(type: Type, mappedKey: MappedKey, options?: SchemaOptions): TIndexFromMappedKey + /** `[Json]` Returns an Indexed property type for the given keys */ + public Index>(T: Type, K: Key, options?: SchemaOptions): TIndex + /** `[Json]` Returns an Indexed property type for the given keys */ + public Index(type: Type, propertyKeys: readonly [...PropertyKeys], options?: SchemaOptions): TIndex /** `[Json]` Returns an Indexed property type for the given keys */ public Index(type: TSchema, key: any, options?: SchemaOptions): any { return Index(type, key, options) diff --git a/src/value/parse/parse.ts b/src/value/parse/parse.ts index be07f5b8..e28d53de 100644 --- a/src/value/parse/parse.ts +++ b/src/value/parse/parse.ts @@ -53,7 +53,7 @@ export class ParseError extends TypeBoxError { // ------------------------------------------------------------------ // ParseRegistry // ------------------------------------------------------------------ -export type TParseOperation = 'Clone' | 'Clean' | 'Default' | 'Convert' | 'Assert' | 'Decode' | ({} & string) +export type TParseOperation = 'Clone' | 'Clean' | 'Default' | 'Convert' | 'Assert' | 'Decode' | 'Encode' | ({} & string) export type TParseFunction = (type: TSchema, references: TSchema[], value: unknown) => unknown // prettier-ignore