From 82df345a4b169f85e51a251a730199419be0fe62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Wed, 19 Feb 2025 11:06:22 +0100 Subject: [PATCH] Revise behavior of mapped types with `any`/`keyof any` constraints --- src/compiler/checker.ts | 10 +++----- .../reference/mappedTypeWithAny.errors.txt | 6 +++++ .../baselines/reference/mappedTypeWithAny.js | 12 +++++++++ .../reference/mappedTypeWithAny.symbols | 17 +++++++++++++ .../reference/mappedTypeWithAny.types | 25 +++++++++++++++++-- .../types/mapped/mappedTypeWithAny.ts | 6 +++++ 6 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index abd6fd4bf2e8d..1e8250b2906c0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14127,7 +14127,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { cb(getLiteralTypeFromProperty(prop, include)); } if (type.flags & TypeFlags.Any) { - cb(stringType); + forEachType(stringsOnly ? stringType : stringNumberSymbolType, cb); } else { for (const info of getIndexInfosOfType(type)) { @@ -14166,7 +14166,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function addMemberForKeyType(keyType: Type) { const propNameType = nameType ? instantiateType(nameType, appendTypeMapping(type.mapper, typeParameter, keyType)) : keyType; - forEachType(propNameType, t => addMemberForKeyTypeWorker(keyType, t)); + forEachType(keyType.flags & TypeFlags.Any ? stringNumberSymbolType : propNameType, t => addMemberForKeyTypeWorker(keyType, t)); } function addMemberForKeyTypeWorker(keyType: Type, propNameType: Type) { @@ -14201,10 +14201,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { members.set(propName, prop); } } - else if (isValidIndexKeyType(propNameType) || propNameType.flags & (TypeFlags.Any | TypeFlags.Enum)) { - const indexKeyType = propNameType.flags & (TypeFlags.Any | TypeFlags.String) ? stringType : - propNameType.flags & (TypeFlags.Number | TypeFlags.Enum) ? numberType : - propNameType; + else if (isValidIndexKeyType(propNameType) || propNameType.flags & TypeFlags.Enum) { + const indexKeyType = propNameType.flags & (TypeFlags.Number | TypeFlags.Enum) ? numberType : propNameType; const propType = instantiateType(templateType, appendTypeMapping(type.mapper, typeParameter, keyType)); const modifiersIndexInfo = getApplicableIndexInfo(modifiersType, propNameType); const isReadonly = !!(templateModifiers & MappedTypeModifiers.IncludeReadonly || diff --git a/tests/baselines/reference/mappedTypeWithAny.errors.txt b/tests/baselines/reference/mappedTypeWithAny.errors.txt index f53402fd7fcb4..e6c3c96f8276f 100644 --- a/tests/baselines/reference/mappedTypeWithAny.errors.txt +++ b/tests/baselines/reference/mappedTypeWithAny.errors.txt @@ -77,4 +77,10 @@ mappedTypeWithAny.ts(53,5): error TS2322: Type 'string[]' is not assignable to t type Evolver = any> = { [key in keyof Partial]: never; }; + + // https://github.com/microsoft/TypeScript/issues/61203 + type Obj61203 = { [k in keyof any]: number }; + declare const obj61203: Obj61203; + declare const key61203: keyof Obj61203; + obj61203[key61203]; // ok \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeWithAny.js b/tests/baselines/reference/mappedTypeWithAny.js index a01d8a6653f42..0ca780968732d 100644 --- a/tests/baselines/reference/mappedTypeWithAny.js +++ b/tests/baselines/reference/mappedTypeWithAny.js @@ -63,6 +63,12 @@ type Evolvable = { type Evolver = any> = { [key in keyof Partial]: never; }; + +// https://github.com/microsoft/TypeScript/issues/61203 +type Obj61203 = { [k in keyof any]: number }; +declare const obj61203: Obj61203; +declare const key61203: keyof Obj61203; +obj61203[key61203]; // ok //// [mappedTypeWithAny.js] @@ -79,6 +85,7 @@ function bar(arrayish, objectish, indirectArrayish) { } var abc = stringifyArray(void 0); var def = stringifyPair(void 0); +obj61203[key61203]; // ok //// [mappedTypeWithAny.d.ts] @@ -128,3 +135,8 @@ type Evolvable = { type Evolver = any> = { [key in keyof Partial]: never; }; +type Obj61203 = { + [k in keyof any]: number; +}; +declare const obj61203: Obj61203; +declare const key61203: keyof Obj61203; diff --git a/tests/baselines/reference/mappedTypeWithAny.symbols b/tests/baselines/reference/mappedTypeWithAny.symbols index b52536f518bc4..1f30122f0af27 100644 --- a/tests/baselines/reference/mappedTypeWithAny.symbols +++ b/tests/baselines/reference/mappedTypeWithAny.symbols @@ -177,3 +177,20 @@ type Evolver = any> = { }; +// https://github.com/microsoft/TypeScript/issues/61203 +type Obj61203 = { [k in keyof any]: number }; +>Obj61203 : Symbol(Obj61203, Decl(mappedTypeWithAny.ts, 61, 2)) +>k : Symbol(k, Decl(mappedTypeWithAny.ts, 64, 19)) + +declare const obj61203: Obj61203; +>obj61203 : Symbol(obj61203, Decl(mappedTypeWithAny.ts, 65, 13)) +>Obj61203 : Symbol(Obj61203, Decl(mappedTypeWithAny.ts, 61, 2)) + +declare const key61203: keyof Obj61203; +>key61203 : Symbol(key61203, Decl(mappedTypeWithAny.ts, 66, 13)) +>Obj61203 : Symbol(Obj61203, Decl(mappedTypeWithAny.ts, 61, 2)) + +obj61203[key61203]; // ok +>obj61203 : Symbol(obj61203, Decl(mappedTypeWithAny.ts, 65, 13)) +>key61203 : Symbol(key61203, Decl(mappedTypeWithAny.ts, 66, 13)) + diff --git a/tests/baselines/reference/mappedTypeWithAny.types b/tests/baselines/reference/mappedTypeWithAny.types index 587ff68bb42f3..eda08236d327d 100644 --- a/tests/baselines/reference/mappedTypeWithAny.types +++ b/tests/baselines/reference/mappedTypeWithAny.types @@ -24,8 +24,8 @@ declare let x2: { [P in string]: Item }; > : ^^^^^^^^^^^^^^^^^^^^^^ declare let x3: { [P in keyof any]: Item }; ->x3 : { [x: string]: Item; } -> : ^^^^^^^^^^^^^^^^^^^^^^ +>x3 : { [x: string]: Item; [x: number]: Item; [x: symbol]: Item; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ declare let x4: ItemMap; >x4 : ItemMap @@ -197,3 +197,24 @@ type Evolver = any> = { [key in keyof Partial]: never; }; +// https://github.com/microsoft/TypeScript/issues/61203 +type Obj61203 = { [k in keyof any]: number }; +>Obj61203 : Obj61203 +> : ^^^^^^^^ + +declare const obj61203: Obj61203; +>obj61203 : Obj61203 +> : ^^^^^^^^ + +declare const key61203: keyof Obj61203; +>key61203 : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + +obj61203[key61203]; // ok +>obj61203[key61203] : number +> : ^^^^^^ +>obj61203 : Obj61203 +> : ^^^^^^^^ +>key61203 : string | number | symbol +> : ^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts index 89c28ddafc68f..52155c6c7867d 100644 --- a/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts +++ b/tests/cases/conformance/types/mapped/mappedTypeWithAny.ts @@ -63,3 +63,9 @@ type Evolvable = { type Evolver = any> = { [key in keyof Partial]: never; }; + +// https://github.com/microsoft/TypeScript/issues/61203 +type Obj61203 = { [k in keyof any]: number }; +declare const obj61203: Obj61203; +declare const key61203: keyof Obj61203; +obj61203[key61203]; // ok