From 745e20987286ef3e83382a6947ed8f013610459a Mon Sep 17 00:00:00 2001 From: umeshmore45 Date: Sun, 8 Mar 2026 15:50:10 +0530 Subject: [PATCH 1/3] fix(declaration-emit): suppress TS4055/TS4073 for protected methods using typeof parameter Made-with: Cursor --- .../protectedMethodTypeofParameter.js | 45 ++++++++++++ .../protectedMethodTypeofParameter.symbols | 57 ++++++++++++++++ .../protectedMethodTypeofParameter.types | 68 +++++++++++++++++++ .../protectedMethodTypeofParameter.ts | 22 ++++++ 4 files changed, 192 insertions(+) create mode 100644 tests/baselines/reference/protectedMethodTypeofParameter.js create mode 100644 tests/baselines/reference/protectedMethodTypeofParameter.symbols create mode 100644 tests/baselines/reference/protectedMethodTypeofParameter.types create mode 100644 tests/cases/compiler/protectedMethodTypeofParameter.ts diff --git a/tests/baselines/reference/protectedMethodTypeofParameter.js b/tests/baselines/reference/protectedMethodTypeofParameter.js new file mode 100644 index 0000000000000..713de599e49c2 --- /dev/null +++ b/tests/baselines/reference/protectedMethodTypeofParameter.js @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/protectedMethodTypeofParameter.ts] //// + +//// [protectedMethodTypeofParameter.ts] +export interface Properties { + propertyA: number; + propertyB: string; +} + +export class A { + public getPropertyValue_Ok( + properties: Properties, + propertyName: keyof Properties, + ): Properties[typeof propertyName] { + return properties[propertyName]; + } + + protected getPropertyValue_Error( + properties: Properties, + propertyName: keyof Properties, + ): Properties[typeof propertyName] { + return properties[propertyName]; + } +} + + +//// [protectedMethodTypeofParameter.js] +export class A { + getPropertyValue_Ok(properties, propertyName) { + return properties[propertyName]; + } + getPropertyValue_Error(properties, propertyName) { + return properties[propertyName]; + } +} + + +//// [protectedMethodTypeofParameter.d.ts] +export interface Properties { + propertyA: number; + propertyB: string; +} +export declare class A { + getPropertyValue_Ok(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; + protected getPropertyValue_Error(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; +} diff --git a/tests/baselines/reference/protectedMethodTypeofParameter.symbols b/tests/baselines/reference/protectedMethodTypeofParameter.symbols new file mode 100644 index 0000000000000..391e783f1597f --- /dev/null +++ b/tests/baselines/reference/protectedMethodTypeofParameter.symbols @@ -0,0 +1,57 @@ +//// [tests/cases/compiler/protectedMethodTypeofParameter.ts] //// + +=== protectedMethodTypeofParameter.ts === +export interface Properties { +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) + + propertyA: number; +>propertyA : Symbol(Properties.propertyA, Decl(protectedMethodTypeofParameter.ts, 0, 29)) + + propertyB: string; +>propertyB : Symbol(Properties.propertyB, Decl(protectedMethodTypeofParameter.ts, 1, 20)) +} + +export class A { +>A : Symbol(A, Decl(protectedMethodTypeofParameter.ts, 3, 1)) + + public getPropertyValue_Ok( +>getPropertyValue_Ok : Symbol(A.getPropertyValue_Ok, Decl(protectedMethodTypeofParameter.ts, 5, 16)) + + properties: Properties, +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 6, 29)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) + + propertyName: keyof Properties, +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 7, 27)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) + + ): Properties[typeof propertyName] { +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 7, 27)) + + return properties[propertyName]; +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 6, 29)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 7, 27)) + } + + protected getPropertyValue_Error( +>getPropertyValue_Error : Symbol(A.getPropertyValue_Error, Decl(protectedMethodTypeofParameter.ts, 11, 3)) + + properties: Properties, +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 35)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) + + propertyName: keyof Properties, +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 14, 27)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) + + ): Properties[typeof propertyName] { +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 14, 27)) + + return properties[propertyName]; +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 35)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 14, 27)) + } +} + diff --git a/tests/baselines/reference/protectedMethodTypeofParameter.types b/tests/baselines/reference/protectedMethodTypeofParameter.types new file mode 100644 index 0000000000000..563ef66655f79 --- /dev/null +++ b/tests/baselines/reference/protectedMethodTypeofParameter.types @@ -0,0 +1,68 @@ +//// [tests/cases/compiler/protectedMethodTypeofParameter.ts] //// + +=== protectedMethodTypeofParameter.ts === +export interface Properties { + propertyA: number; +>propertyA : number +> : ^^^^^^ + + propertyB: string; +>propertyB : string +> : ^^^^^^ +} + +export class A { +>A : A +> : ^ + + public getPropertyValue_Ok( +>getPropertyValue_Ok : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName] +> : ^ ^^ ^^ ^^ ^^^^^ + + properties: Properties, +>properties : Properties +> : ^^^^^^^^^^ + + propertyName: keyof Properties, +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + + ): Properties[typeof propertyName] { +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + + return properties[propertyName]; +>properties[propertyName] : string | number +> : ^^^^^^^^^^^^^^^ +>properties : Properties +> : ^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + } + + protected getPropertyValue_Error( +>getPropertyValue_Error : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName] +> : ^ ^^ ^^ ^^ ^^^^^ + + properties: Properties, +>properties : Properties +> : ^^^^^^^^^^ + + propertyName: keyof Properties, +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + + ): Properties[typeof propertyName] { +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + + return properties[propertyName]; +>properties[propertyName] : string | number +> : ^^^^^^^^^^^^^^^ +>properties : Properties +> : ^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + } +} + diff --git a/tests/cases/compiler/protectedMethodTypeofParameter.ts b/tests/cases/compiler/protectedMethodTypeofParameter.ts new file mode 100644 index 0000000000000..463494ff9494e --- /dev/null +++ b/tests/cases/compiler/protectedMethodTypeofParameter.ts @@ -0,0 +1,22 @@ +// @declaration: true + +export interface Properties { + propertyA: number; + propertyB: string; +} + +export class A { + public getPropertyValue_Ok( + properties: Properties, + propertyName: keyof Properties, + ): Properties[typeof propertyName] { + return properties[propertyName]; + } + + protected getPropertyValue_Error( + properties: Properties, + propertyName: keyof Properties, + ): Properties[typeof propertyName] { + return properties[propertyName]; + } +} From c00009022c2da835deebca0ebd8a3d100f4c26a5 Mon Sep 17 00:00:00 2001 From: umeshmore45 Date: Sun, 8 Mar 2026 17:34:48 +0530 Subject: [PATCH 2/3] fix(checker): treat typeof parameter as accessible in declaration emit Parameters are always in scope within their enclosing function. When `typeof paramName` is used in a return type annotation, the parameter symbol should be considered accessible regardless of method visibility (public, protected, private), just like type parameters are. Previously, `isEntityNameVisible` would fall through to `hasVisibleDeclarations` for parameter symbols, which returned `undefined` (parameters are not module-level exports), causing a false-positive TS4055/TS4073 error for protected methods using `typeof parameter` in their return type. Fixes the case: protected method(): Properties[typeof paramName] -- no longer emits TS4055 --- src/compiler/checker.ts | 5 ++ ...InternalTypesProduceUniqueTypeParams.types | 8 +-- .../protectedMethodTypeofParameter.d.symbols | 44 +++++++++++++++++ .../protectedMethodTypeofParameter.d.types | 49 +++++++++++++++++++ .../protectedMethodTypeofParameter.js | 22 +++++++-- .../protectedMethodTypeofParameter.symbols | 35 +++++++++++-- .../protectedMethodTypeofParameter.types | 44 +++++++++++++++-- .../protectedMethodTypeofParameter.d.ts | 9 ++++ .../protectedMethodTypeofParameter.ts | 12 ++++- 9 files changed, 213 insertions(+), 15 deletions(-) create mode 100644 tests/baselines/reference/protectedMethodTypeofParameter.d.symbols create mode 100644 tests/baselines/reference/protectedMethodTypeofParameter.d.types create mode 100644 tests/cases/compiler/protectedMethodTypeofParameter.d.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0567712f11da3..06c06d1b749e2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6158,6 +6158,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { errorNode: firstIdentifier, }; } + // Parameters are always in scope within their enclosing function; `typeof paramName` in a + // return type annotation is valid regardless of method visibility (public, protected, private). + if (symbol.declarations && every(symbol.declarations, isParameter)) { + return { accessibility: SymbolAccessibility.Accessible }; + } // Verify if the symbol is accessible return hasVisibleDeclarations(symbol, shouldComputeAliasToMakeVisible) || { accessibility: SymbolAccessibility.NotAccessible, diff --git a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types index 9c70dfeee5136..7983e9548719a 100644 --- a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types +++ b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types @@ -104,8 +104,8 @@ export const updateIfChanged = (t: T) => { > : ^ >update : (u: U) => T > : ^ ^^ ^^^^^ ->Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }) : U & { [x: string]: Value; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }) : U & { [key]: Value; } +> : ^^^^^^ ^^^^^^^^^^^ ^^ >Object.assign : { (target: T_1, source: U_1): T_1 & U_1; (target: T_1, source1: U_1, source2: V): T_1 & U_1 & V; (target: T_1, source1: U_1, source2: V, source3: W): T_1 & U_1 & V & W; (target: object, ...sources: any[]): any; } > : ^^^^^^^^^^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^^ ^^^^^^^^^^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^^^^^^^^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^ ^^^^^ ^^ ^^^ ^^^ >Object : ObjectConstructor @@ -130,8 +130,8 @@ export const updateIfChanged = (t: T) => { > : ^^ >u : U > : ^ ->{ [key]: v } : { [x: string]: Value; } -> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +>{ [key]: v } : { [key]: Value; } +> : ^^ ^^^^^^^^^^^ ^^ >[key] : Value > : ^^^^^^^^^^^ >key : K diff --git a/tests/baselines/reference/protectedMethodTypeofParameter.d.symbols b/tests/baselines/reference/protectedMethodTypeofParameter.d.symbols new file mode 100644 index 0000000000000..571f3fcde26d0 --- /dev/null +++ b/tests/baselines/reference/protectedMethodTypeofParameter.d.symbols @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/protectedMethodTypeofParameter.d.ts] //// + +=== protectedMethodTypeofParameter.d.ts === +export interface Properties { +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) + + propertyA: number; +>propertyA : Symbol(Properties.propertyA, Decl(protectedMethodTypeofParameter.d.ts, 0, 29)) + + propertyB: string; +>propertyB : Symbol(Properties.propertyB, Decl(protectedMethodTypeofParameter.d.ts, 1, 22)) +} +export declare class A { +>A : Symbol(A, Decl(protectedMethodTypeofParameter.d.ts, 3, 1)) + + getPropertyValue_Ok(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; +>getPropertyValue_Ok : Symbol(A.getPropertyValue_Ok, Decl(protectedMethodTypeofParameter.d.ts, 4, 24)) +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.d.ts, 5, 24)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 5, 47)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 5, 47)) + + protected getPropertyValue_Protected(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; +>getPropertyValue_Protected : Symbol(A.getPropertyValue_Protected, Decl(protectedMethodTypeofParameter.d.ts, 5, 113)) +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.d.ts, 6, 41)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 6, 64)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 6, 64)) + + protected setPropertyValue_Protected(properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]): void; +>setPropertyValue_Protected : Symbol(A.setPropertyValue_Protected, Decl(protectedMethodTypeofParameter.d.ts, 6, 130)) +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.d.ts, 7, 41)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 7, 64)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) +>propertyValue : Symbol(propertyValue, Decl(protectedMethodTypeofParameter.d.ts, 7, 96)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 7, 64)) +} + diff --git a/tests/baselines/reference/protectedMethodTypeofParameter.d.types b/tests/baselines/reference/protectedMethodTypeofParameter.d.types new file mode 100644 index 0000000000000..e38b4b26e50ed --- /dev/null +++ b/tests/baselines/reference/protectedMethodTypeofParameter.d.types @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/protectedMethodTypeofParameter.d.ts] //// + +=== protectedMethodTypeofParameter.d.ts === +export interface Properties { + propertyA: number; +>propertyA : number +> : ^^^^^^ + + propertyB: string; +>propertyB : string +> : ^^^^^^ +} +export declare class A { +>A : A +> : ^ + + getPropertyValue_Ok(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; +>getPropertyValue_Ok : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName] +> : ^ ^^ ^^ ^^ ^^^^^ +>properties : Properties +> : ^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + + protected getPropertyValue_Protected(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; +>getPropertyValue_Protected : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName] +> : ^ ^^ ^^ ^^ ^^^^^ +>properties : Properties +> : ^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + + protected setPropertyValue_Protected(properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]): void; +>setPropertyValue_Protected : (properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]) => void +> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^ +>properties : Properties +> : ^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ +>propertyValue : string | number +> : ^^^^^^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ +} + diff --git a/tests/baselines/reference/protectedMethodTypeofParameter.js b/tests/baselines/reference/protectedMethodTypeofParameter.js index 713de599e49c2..98c9c7fa5cace 100644 --- a/tests/baselines/reference/protectedMethodTypeofParameter.js +++ b/tests/baselines/reference/protectedMethodTypeofParameter.js @@ -14,12 +14,22 @@ export class A { return properties[propertyName]; } - protected getPropertyValue_Error( + protected getPropertyValue_Protected( properties: Properties, propertyName: keyof Properties, ): Properties[typeof propertyName] { return properties[propertyName]; } + + protected setPropertyValue_Protected( + properties: Properties, + propertyName: keyof Properties, + propertyValue: Properties[typeof propertyName], + ): void { + void properties; + void propertyName; + void propertyValue; + } } @@ -28,9 +38,14 @@ export class A { getPropertyValue_Ok(properties, propertyName) { return properties[propertyName]; } - getPropertyValue_Error(properties, propertyName) { + getPropertyValue_Protected(properties, propertyName) { return properties[propertyName]; } + setPropertyValue_Protected(properties, propertyName, propertyValue) { + void properties; + void propertyName; + void propertyValue; + } } @@ -41,5 +56,6 @@ export interface Properties { } export declare class A { getPropertyValue_Ok(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; - protected getPropertyValue_Error(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; + protected getPropertyValue_Protected(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; + protected setPropertyValue_Protected(properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]): void; } diff --git a/tests/baselines/reference/protectedMethodTypeofParameter.symbols b/tests/baselines/reference/protectedMethodTypeofParameter.symbols index 391e783f1597f..277809e120cfd 100644 --- a/tests/baselines/reference/protectedMethodTypeofParameter.symbols +++ b/tests/baselines/reference/protectedMethodTypeofParameter.symbols @@ -34,11 +34,11 @@ export class A { >propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 7, 27)) } - protected getPropertyValue_Error( ->getPropertyValue_Error : Symbol(A.getPropertyValue_Error, Decl(protectedMethodTypeofParameter.ts, 11, 3)) + protected getPropertyValue_Protected( +>getPropertyValue_Protected : Symbol(A.getPropertyValue_Protected, Decl(protectedMethodTypeofParameter.ts, 11, 3)) properties: Properties, ->properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 35)) +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 39)) >Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) propertyName: keyof Properties, @@ -50,8 +50,35 @@ export class A { >propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 14, 27)) return properties[propertyName]; ->properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 35)) +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 39)) >propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 14, 27)) } + + protected setPropertyValue_Protected( +>setPropertyValue_Protected : Symbol(A.setPropertyValue_Protected, Decl(protectedMethodTypeofParameter.ts, 18, 3)) + + properties: Properties, +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 20, 39)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) + + propertyName: keyof Properties, +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 21, 27)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) + + propertyValue: Properties[typeof propertyName], +>propertyValue : Symbol(propertyValue, Decl(protectedMethodTypeofParameter.ts, 22, 35)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 21, 27)) + + ): void { + void properties; +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 20, 39)) + + void propertyName; +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 21, 27)) + + void propertyValue; +>propertyValue : Symbol(propertyValue, Decl(protectedMethodTypeofParameter.ts, 22, 35)) + } } diff --git a/tests/baselines/reference/protectedMethodTypeofParameter.types b/tests/baselines/reference/protectedMethodTypeofParameter.types index 563ef66655f79..f4a1b0a46ac1d 100644 --- a/tests/baselines/reference/protectedMethodTypeofParameter.types +++ b/tests/baselines/reference/protectedMethodTypeofParameter.types @@ -40,9 +40,9 @@ export class A { > : ^^^^^^^^^^^^^^^^ } - protected getPropertyValue_Error( ->getPropertyValue_Error : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName] -> : ^ ^^ ^^ ^^ ^^^^^ + protected getPropertyValue_Protected( +>getPropertyValue_Protected : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName] +> : ^ ^^ ^^ ^^ ^^^^^ properties: Properties, >properties : Properties @@ -64,5 +64,43 @@ export class A { >propertyName : keyof Properties > : ^^^^^^^^^^^^^^^^ } + + protected setPropertyValue_Protected( +>setPropertyValue_Protected : (properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]) => void +> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^ + + properties: Properties, +>properties : Properties +> : ^^^^^^^^^^ + + propertyName: keyof Properties, +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + + propertyValue: Properties[typeof propertyName], +>propertyValue : string | number +> : ^^^^^^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + + ): void { + void properties; +>void properties : undefined +> : ^^^^^^^^^ +>properties : Properties +> : ^^^^^^^^^^ + + void propertyName; +>void propertyName : undefined +> : ^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ + + void propertyValue; +>void propertyValue : undefined +> : ^^^^^^^^^ +>propertyValue : string | number +> : ^^^^^^^^^^^^^^^ + } } diff --git a/tests/cases/compiler/protectedMethodTypeofParameter.d.ts b/tests/cases/compiler/protectedMethodTypeofParameter.d.ts new file mode 100644 index 0000000000000..2c7a1a3f58249 --- /dev/null +++ b/tests/cases/compiler/protectedMethodTypeofParameter.d.ts @@ -0,0 +1,9 @@ +export interface Properties { + propertyA: number; + propertyB: string; +} +export declare class A { + getPropertyValue_Ok(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; + protected getPropertyValue_Protected(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; + protected setPropertyValue_Protected(properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]): void; +} diff --git a/tests/cases/compiler/protectedMethodTypeofParameter.ts b/tests/cases/compiler/protectedMethodTypeofParameter.ts index 463494ff9494e..a9b16b5c15d15 100644 --- a/tests/cases/compiler/protectedMethodTypeofParameter.ts +++ b/tests/cases/compiler/protectedMethodTypeofParameter.ts @@ -13,10 +13,20 @@ export class A { return properties[propertyName]; } - protected getPropertyValue_Error( + protected getPropertyValue_Protected( properties: Properties, propertyName: keyof Properties, ): Properties[typeof propertyName] { return properties[propertyName]; } + + protected setPropertyValue_Protected( + properties: Properties, + propertyName: keyof Properties, + propertyValue: Properties[typeof propertyName], + ): void { + void properties; + void propertyName; + void propertyValue; + } } From b7e67fa20f9af9c3989a4a20399db6d3e4ac36f6 Mon Sep 17 00:00:00 2001 From: umeshmore45 Date: Sun, 8 Mar 2026 18:31:55 +0530 Subject: [PATCH 3/3] fix(checker): narrow accessibility check for typeof parameters in type queries Refined the accessibility check for parameter symbols to only apply when they are part of a TypeQuery. This prevents parameter identifiers used as computed property names in type printing from being incorrectly treated as accessible unique-symbol-like keys. --- src/compiler/checker.ts | 5 ++++- ...ithRecursiveInternalTypesProduceUniqueTypeParams.types | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 06c06d1b749e2..4e60bd87603e1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6160,7 +6160,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // Parameters are always in scope within their enclosing function; `typeof paramName` in a // return type annotation is valid regardless of method visibility (public, protected, private). - if (symbol.declarations && every(symbol.declarations, isParameter)) { + // Narrow this exception to TypeQuery nodes only (e.g. `typeof param`) so that parameter + // identifiers used as computed property names in type printing are not incorrectly treated + // as accessible unique-symbol-like keys. + if (symbol.declarations && every(symbol.declarations, isParameter) && isPartOfTypeQuery(entityName)) { return { accessibility: SymbolAccessibility.Accessible }; } // Verify if the symbol is accessible diff --git a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types index 7983e9548719a..9c70dfeee5136 100644 --- a/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types +++ b/tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types @@ -104,8 +104,8 @@ export const updateIfChanged = (t: T) => { > : ^ >update : (u: U) => T > : ^ ^^ ^^^^^ ->Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }) : U & { [key]: Value; } -> : ^^^^^^ ^^^^^^^^^^^ ^^ +>Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }) : U & { [x: string]: Value; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >Object.assign : { (target: T_1, source: U_1): T_1 & U_1; (target: T_1, source1: U_1, source2: V): T_1 & U_1 & V; (target: T_1, source1: U_1, source2: V, source3: W): T_1 & U_1 & V & W; (target: object, ...sources: any[]): any; } > : ^^^^^^^^^^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^^ ^^^^^^^^^^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^^^^^^^^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^ ^^^^^ ^^ ^^^ ^^^ >Object : ObjectConstructor @@ -130,8 +130,8 @@ export const updateIfChanged = (t: T) => { > : ^^ >u : U > : ^ ->{ [key]: v } : { [key]: Value; } -> : ^^ ^^^^^^^^^^^ ^^ +>{ [key]: v } : { [x: string]: Value; } +> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ >[key] : Value > : ^^^^^^^^^^^ >key : K