Skip to content

Commit c000090

Browse files
committed
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
1 parent 745e209 commit c000090

9 files changed

+213
-15
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6158,6 +6158,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
61586158
errorNode: firstIdentifier,
61596159
};
61606160
}
6161+
// Parameters are always in scope within their enclosing function; `typeof paramName` in a
6162+
// return type annotation is valid regardless of method visibility (public, protected, private).
6163+
if (symbol.declarations && every(symbol.declarations, isParameter)) {
6164+
return { accessibility: SymbolAccessibility.Accessible };
6165+
}
61616166
// Verify if the symbol is accessible
61626167
return hasVisibleDeclarations(symbol, shouldComputeAliasToMakeVisible) || {
61636168
accessibility: SymbolAccessibility.NotAccessible,

tests/baselines/reference/declarationsWithRecursiveInternalTypesProduceUniqueTypeParams.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ export const updateIfChanged = <T>(t: T) => {
104104
> : ^
105105
>update : (u: U) => T
106106
> : ^ ^^ ^^^^^
107-
>Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }) : U & { [x: string]: Value<K, U>; }
108-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
107+
>Object.assign(Array.isArray(u) ? [] : {}, u, { [key]: v }) : U & { [key]: Value<K, U>; }
108+
> : ^^^^^^ ^^^^^^^^^^^ ^^
109109
>Object.assign : { <T_1 extends {}, U_1>(target: T_1, source: U_1): T_1 & U_1; <T_1 extends {}, U_1, V>(target: T_1, source1: U_1, source2: V): T_1 & U_1 & V; <T_1 extends {}, U_1, V, W>(target: T_1, source1: U_1, source2: V, source3: W): T_1 & U_1 & V & W; (target: object, ...sources: any[]): any; }
110110
> : ^^^^^^^^^^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^^ ^^^^^^^^^^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^^^^^^^^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^ ^^^ ^^ ^^^^^ ^^ ^^^ ^^^
111111
>Object : ObjectConstructor
@@ -130,8 +130,8 @@ export const updateIfChanged = <T>(t: T) => {
130130
> : ^^
131131
>u : U
132132
> : ^
133-
>{ [key]: v } : { [x: string]: Value<K, U>; }
134-
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
133+
>{ [key]: v } : { [key]: Value<K, U>; }
134+
> : ^^ ^^^^^^^^^^^ ^^
135135
>[key] : Value<K, U>
136136
> : ^^^^^^^^^^^
137137
>key : K
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//// [tests/cases/compiler/protectedMethodTypeofParameter.d.ts] ////
2+
3+
=== protectedMethodTypeofParameter.d.ts ===
4+
export interface Properties {
5+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0))
6+
7+
propertyA: number;
8+
>propertyA : Symbol(Properties.propertyA, Decl(protectedMethodTypeofParameter.d.ts, 0, 29))
9+
10+
propertyB: string;
11+
>propertyB : Symbol(Properties.propertyB, Decl(protectedMethodTypeofParameter.d.ts, 1, 22))
12+
}
13+
export declare class A {
14+
>A : Symbol(A, Decl(protectedMethodTypeofParameter.d.ts, 3, 1))
15+
16+
getPropertyValue_Ok(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName];
17+
>getPropertyValue_Ok : Symbol(A.getPropertyValue_Ok, Decl(protectedMethodTypeofParameter.d.ts, 4, 24))
18+
>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.d.ts, 5, 24))
19+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0))
20+
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 5, 47))
21+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0))
22+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0))
23+
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 5, 47))
24+
25+
protected getPropertyValue_Protected(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName];
26+
>getPropertyValue_Protected : Symbol(A.getPropertyValue_Protected, Decl(protectedMethodTypeofParameter.d.ts, 5, 113))
27+
>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.d.ts, 6, 41))
28+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0))
29+
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 6, 64))
30+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0))
31+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0))
32+
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 6, 64))
33+
34+
protected setPropertyValue_Protected(properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]): void;
35+
>setPropertyValue_Protected : Symbol(A.setPropertyValue_Protected, Decl(protectedMethodTypeofParameter.d.ts, 6, 130))
36+
>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.d.ts, 7, 41))
37+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0))
38+
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 7, 64))
39+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0))
40+
>propertyValue : Symbol(propertyValue, Decl(protectedMethodTypeofParameter.d.ts, 7, 96))
41+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.d.ts, 0, 0))
42+
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.d.ts, 7, 64))
43+
}
44+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//// [tests/cases/compiler/protectedMethodTypeofParameter.d.ts] ////
2+
3+
=== protectedMethodTypeofParameter.d.ts ===
4+
export interface Properties {
5+
propertyA: number;
6+
>propertyA : number
7+
> : ^^^^^^
8+
9+
propertyB: string;
10+
>propertyB : string
11+
> : ^^^^^^
12+
}
13+
export declare class A {
14+
>A : A
15+
> : ^
16+
17+
getPropertyValue_Ok(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName];
18+
>getPropertyValue_Ok : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName]
19+
> : ^ ^^ ^^ ^^ ^^^^^
20+
>properties : Properties
21+
> : ^^^^^^^^^^
22+
>propertyName : keyof Properties
23+
> : ^^^^^^^^^^^^^^^^
24+
>propertyName : keyof Properties
25+
> : ^^^^^^^^^^^^^^^^
26+
27+
protected getPropertyValue_Protected(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName];
28+
>getPropertyValue_Protected : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName]
29+
> : ^ ^^ ^^ ^^ ^^^^^
30+
>properties : Properties
31+
> : ^^^^^^^^^^
32+
>propertyName : keyof Properties
33+
> : ^^^^^^^^^^^^^^^^
34+
>propertyName : keyof Properties
35+
> : ^^^^^^^^^^^^^^^^
36+
37+
protected setPropertyValue_Protected(properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]): void;
38+
>setPropertyValue_Protected : (properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]) => void
39+
> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^
40+
>properties : Properties
41+
> : ^^^^^^^^^^
42+
>propertyName : keyof Properties
43+
> : ^^^^^^^^^^^^^^^^
44+
>propertyValue : string | number
45+
> : ^^^^^^^^^^^^^^^
46+
>propertyName : keyof Properties
47+
> : ^^^^^^^^^^^^^^^^
48+
}
49+

tests/baselines/reference/protectedMethodTypeofParameter.js

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,22 @@ export class A {
1414
return properties[propertyName];
1515
}
1616

17-
protected getPropertyValue_Error(
17+
protected getPropertyValue_Protected(
1818
properties: Properties,
1919
propertyName: keyof Properties,
2020
): Properties[typeof propertyName] {
2121
return properties[propertyName];
2222
}
23+
24+
protected setPropertyValue_Protected(
25+
properties: Properties,
26+
propertyName: keyof Properties,
27+
propertyValue: Properties[typeof propertyName],
28+
): void {
29+
void properties;
30+
void propertyName;
31+
void propertyValue;
32+
}
2333
}
2434

2535

@@ -28,9 +38,14 @@ export class A {
2838
getPropertyValue_Ok(properties, propertyName) {
2939
return properties[propertyName];
3040
}
31-
getPropertyValue_Error(properties, propertyName) {
41+
getPropertyValue_Protected(properties, propertyName) {
3242
return properties[propertyName];
3343
}
44+
setPropertyValue_Protected(properties, propertyName, propertyValue) {
45+
void properties;
46+
void propertyName;
47+
void propertyValue;
48+
}
3449
}
3550

3651

@@ -41,5 +56,6 @@ export interface Properties {
4156
}
4257
export declare class A {
4358
getPropertyValue_Ok(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName];
44-
protected getPropertyValue_Error(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName];
59+
protected getPropertyValue_Protected(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName];
60+
protected setPropertyValue_Protected(properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]): void;
4561
}

tests/baselines/reference/protectedMethodTypeofParameter.symbols

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ export class A {
3434
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 7, 27))
3535
}
3636

37-
protected getPropertyValue_Error(
38-
>getPropertyValue_Error : Symbol(A.getPropertyValue_Error, Decl(protectedMethodTypeofParameter.ts, 11, 3))
37+
protected getPropertyValue_Protected(
38+
>getPropertyValue_Protected : Symbol(A.getPropertyValue_Protected, Decl(protectedMethodTypeofParameter.ts, 11, 3))
3939

4040
properties: Properties,
41-
>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 35))
41+
>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 39))
4242
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0))
4343

4444
propertyName: keyof Properties,
@@ -50,8 +50,35 @@ export class A {
5050
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 14, 27))
5151

5252
return properties[propertyName];
53-
>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 35))
53+
>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 13, 39))
5454
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 14, 27))
5555
}
56+
57+
protected setPropertyValue_Protected(
58+
>setPropertyValue_Protected : Symbol(A.setPropertyValue_Protected, Decl(protectedMethodTypeofParameter.ts, 18, 3))
59+
60+
properties: Properties,
61+
>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 20, 39))
62+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0))
63+
64+
propertyName: keyof Properties,
65+
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 21, 27))
66+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0))
67+
68+
propertyValue: Properties[typeof propertyName],
69+
>propertyValue : Symbol(propertyValue, Decl(protectedMethodTypeofParameter.ts, 22, 35))
70+
>Properties : Symbol(Properties, Decl(protectedMethodTypeofParameter.ts, 0, 0))
71+
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 21, 27))
72+
73+
): void {
74+
void properties;
75+
>properties : Symbol(properties, Decl(protectedMethodTypeofParameter.ts, 20, 39))
76+
77+
void propertyName;
78+
>propertyName : Symbol(propertyName, Decl(protectedMethodTypeofParameter.ts, 21, 27))
79+
80+
void propertyValue;
81+
>propertyValue : Symbol(propertyValue, Decl(protectedMethodTypeofParameter.ts, 22, 35))
82+
}
5683
}
5784

tests/baselines/reference/protectedMethodTypeofParameter.types

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ export class A {
4040
> : ^^^^^^^^^^^^^^^^
4141
}
4242

43-
protected getPropertyValue_Error(
44-
>getPropertyValue_Error : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName]
45-
> : ^ ^^ ^^ ^^ ^^^^^
43+
protected getPropertyValue_Protected(
44+
>getPropertyValue_Protected : (properties: Properties, propertyName: keyof Properties) => Properties[typeof propertyName]
45+
> : ^ ^^ ^^ ^^ ^^^^^
4646

4747
properties: Properties,
4848
>properties : Properties
@@ -64,5 +64,43 @@ export class A {
6464
>propertyName : keyof Properties
6565
> : ^^^^^^^^^^^^^^^^
6666
}
67+
68+
protected setPropertyValue_Protected(
69+
>setPropertyValue_Protected : (properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]) => void
70+
> : ^ ^^ ^^ ^^ ^^ ^^ ^^^^^
71+
72+
properties: Properties,
73+
>properties : Properties
74+
> : ^^^^^^^^^^
75+
76+
propertyName: keyof Properties,
77+
>propertyName : keyof Properties
78+
> : ^^^^^^^^^^^^^^^^
79+
80+
propertyValue: Properties[typeof propertyName],
81+
>propertyValue : string | number
82+
> : ^^^^^^^^^^^^^^^
83+
>propertyName : keyof Properties
84+
> : ^^^^^^^^^^^^^^^^
85+
86+
): void {
87+
void properties;
88+
>void properties : undefined
89+
> : ^^^^^^^^^
90+
>properties : Properties
91+
> : ^^^^^^^^^^
92+
93+
void propertyName;
94+
>void propertyName : undefined
95+
> : ^^^^^^^^^
96+
>propertyName : keyof Properties
97+
> : ^^^^^^^^^^^^^^^^
98+
99+
void propertyValue;
100+
>void propertyValue : undefined
101+
> : ^^^^^^^^^
102+
>propertyValue : string | number
103+
> : ^^^^^^^^^^^^^^^
104+
}
67105
}
68106

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface Properties {
2+
propertyA: number;
3+
propertyB: string;
4+
}
5+
export declare class A {
6+
getPropertyValue_Ok(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName];
7+
protected getPropertyValue_Protected(properties: Properties, propertyName: keyof Properties): Properties[typeof propertyName];
8+
protected setPropertyValue_Protected(properties: Properties, propertyName: keyof Properties, propertyValue: Properties[typeof propertyName]): void;
9+
}

tests/cases/compiler/protectedMethodTypeofParameter.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,20 @@ export class A {
1313
return properties[propertyName];
1414
}
1515

16-
protected getPropertyValue_Error(
16+
protected getPropertyValue_Protected(
1717
properties: Properties,
1818
propertyName: keyof Properties,
1919
): Properties[typeof propertyName] {
2020
return properties[propertyName];
2121
}
22+
23+
protected setPropertyValue_Protected(
24+
properties: Properties,
25+
propertyName: keyof Properties,
26+
propertyValue: Properties[typeof propertyName],
27+
): void {
28+
void properties;
29+
void propertyName;
30+
void propertyValue;
31+
}
2232
}

0 commit comments

Comments
 (0)