diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0567712f11da3..4e60bd87603e1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6158,6 +6158,14 @@ 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). + // 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 return hasVisibleDeclarations(symbol, shouldComputeAliasToMakeVisible) || { accessibility: SymbolAccessibility.NotAccessible, 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 new file mode 100644 index 0000000000000..98c9c7fa5cace --- /dev/null +++ b/tests/baselines/reference/protectedMethodTypeofParameter.js @@ -0,0 +1,61 @@ +//// [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_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; + } +} + + +//// [protectedMethodTypeofParameter.js] +export class A { + getPropertyValue_Ok(properties, propertyName) { + return properties[propertyName]; + } + getPropertyValue_Protected(properties, propertyName) { + return properties[propertyName]; + } + setPropertyValue_Protected(properties, propertyName, propertyValue) { + void properties; + void propertyName; + void propertyValue; + } +} + + +//// [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_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 new file mode 100644 index 0000000000000..277809e120cfd --- /dev/null +++ b/tests/baselines/reference/protectedMethodTypeofParameter.symbols @@ -0,0 +1,84 @@ +//// [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_Protected( +>getPropertyValue_Protected : Symbol(A.getPropertyValue_Protected, Decl(protectedMethodTypeofParameter.ts, 11, 3)) + + properties: Properties, +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 39)) +>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, 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 new file mode 100644 index 0000000000000..f4a1b0a46ac1d --- /dev/null +++ b/tests/baselines/reference/protectedMethodTypeofParameter.types @@ -0,0 +1,106 @@ +//// [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_Protected( +>getPropertyValue_Protected : (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 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 new file mode 100644 index 0000000000000..a9b16b5c15d15 --- /dev/null +++ b/tests/cases/compiler/protectedMethodTypeofParameter.ts @@ -0,0 +1,32 @@ +// @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_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; + } +}