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/src/compiler/transformers/declarations/diagnostics.ts b/src/compiler/transformers/declarations/diagnostics.ts index 873f23cbf7987..1915820bd932f 100644 --- a/src/compiler/transformers/declarations/diagnostics.ts +++ b/src/compiler/transformers/declarations/diagnostics.ts @@ -353,7 +353,7 @@ export function createGetSymbolAccessibilityDiagnosticForNode(node: DeclarationD }; } - function getReturnTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + function getReturnTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic | undefined { let diagnosticMessage: DiagnosticMessage; switch (node.kind) { case SyntaxKind.ConstructSignature: diff --git a/tests/baselines/reference/protectedMethodTypeofParameter.d.symbols b/tests/baselines/reference/protectedMethodTypeofParameter.d.symbols new file mode 100644 index 0000000000000..d739ff7dbb472 --- /dev/null +++ b/tests/baselines/reference/protectedMethodTypeofParameter.d.symbols @@ -0,0 +1,34 @@ +//// [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_Error(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; +>getPropertyValue_Error : Symbol(A.getPropertyValue_Error, Decl(protectedMethodTypeofParameter.d.ts, 5, 113)) +>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.d.ts, 6, 37)) +>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0)) +>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 6, 60)) +>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, 60)) +} + diff --git a/tests/baselines/reference/protectedMethodTypeofParameter.d.types b/tests/baselines/reference/protectedMethodTypeofParameter.d.types new file mode 100644 index 0000000000000..006bae46cbece --- /dev/null +++ b/tests/baselines/reference/protectedMethodTypeofParameter.d.types @@ -0,0 +1,37 @@ +//// [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_Error(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName]; +>getPropertyValue_Error : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName] +> : ^ ^^ ^^ ^^ ^^^^^ +>properties : Properties +> : ^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ +>propertyName : keyof Properties +> : ^^^^^^^^^^^^^^^^ +} + 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.d.ts b/tests/cases/compiler/protectedMethodTypeofParameter.d.ts new file mode 100644 index 0000000000000..8215fb0ad5865 --- /dev/null +++ b/tests/cases/compiler/protectedMethodTypeofParameter.d.ts @@ -0,0 +1,8 @@ +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/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]; + } +}