Skip to content

Commit 898edb5

Browse files
TypeScript Botahejlsberg
TypeScript Bot
andauthored
🤖 Pick PR #54208 (Properly handle typeof this.xxx i...) into release-5.1 (#54413)
Co-authored-by: Anders Hejlsberg <[email protected]>
1 parent 42e7839 commit 898edb5

File tree

4 files changed

+71
-19
lines changed

4 files changed

+71
-19
lines changed

Diff for: ‎src/compiler/checker.ts

+10-19
Original file line numberDiff line numberDiff line change
@@ -18813,25 +18813,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1881318813
case SyntaxKind.TypeQuery:
1881418814
const entityName = (node as TypeQueryNode).exprName;
1881518815
const firstIdentifier = getFirstIdentifier(entityName);
18816-
const firstIdentifierSymbol = getResolvedSymbol(firstIdentifier);
18817-
const tpDeclaration = tp.symbol.declarations![0]; // There is exactly one declaration, otherwise `containsReference` is not called
18818-
let tpScope: Node;
18819-
if (tpDeclaration.kind === SyntaxKind.TypeParameter) { // Type parameter is a regular type parameter, e.g. foo<T>
18820-
tpScope = tpDeclaration.parent;
18821-
}
18822-
else if (tp.isThisType) {
18823-
// Type parameter is the this type, and its declaration is the class declaration.
18824-
tpScope = tpDeclaration;
18825-
}
18826-
else {
18827-
// Type parameter's declaration was unrecognized.
18828-
// This could happen if the type parameter comes from e.g. a JSDoc annotation, so we default to returning true.
18829-
return true;
18830-
}
18831-
18832-
if (firstIdentifierSymbol.declarations) {
18833-
return some(firstIdentifierSymbol.declarations, idDecl => isNodeDescendantOf(idDecl, tpScope)) ||
18834-
some((node as TypeQueryNode).typeArguments, containsReference);
18816+
if (!isThisIdentifier(firstIdentifier)) { // Don't attempt to analyze typeof this.xxx
18817+
const firstIdentifierSymbol = getResolvedSymbol(firstIdentifier);
18818+
const tpDeclaration = tp.symbol.declarations![0]; // There is exactly one declaration, otherwise `containsReference` is not called
18819+
const tpScope = tpDeclaration.kind === SyntaxKind.TypeParameter ? tpDeclaration.parent : // Type parameter is a regular type parameter, e.g. foo<T>
18820+
tp.isThisType ? tpDeclaration : // Type parameter is the this type, and its declaration is the class declaration.
18821+
undefined; // Type parameter's declaration was unrecognized, e.g. comes from JSDoc annotation.
18822+
if (firstIdentifierSymbol.declarations && tpScope) {
18823+
return some(firstIdentifierSymbol.declarations, idDecl => isNodeDescendantOf(idDecl, tpScope)) ||
18824+
some((node as TypeQueryNode).typeArguments, containsReference);
18825+
}
1883518826
}
1883618827
return true;
1883718828
case SyntaxKind.MethodDeclaration:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
=== tests/cases/compiler/typeofThisInMethodSignature.ts ===
2+
// Repro from #54167
3+
4+
export class A {
5+
>A : Symbol(A, Decl(typeofThisInMethodSignature.ts, 0, 0))
6+
7+
x = 1
8+
>x : Symbol(A.x, Decl(typeofThisInMethodSignature.ts, 2, 16))
9+
10+
a(x: typeof this.x): void {}
11+
>a : Symbol(A.a, Decl(typeofThisInMethodSignature.ts, 3, 6))
12+
>x : Symbol(x, Decl(typeofThisInMethodSignature.ts, 4, 3))
13+
>this.x : Symbol(A.x, Decl(typeofThisInMethodSignature.ts, 2, 16))
14+
>this : Symbol(A, Decl(typeofThisInMethodSignature.ts, 0, 0))
15+
>x : Symbol(A.x, Decl(typeofThisInMethodSignature.ts, 2, 16))
16+
}
17+
18+
const a = new A().a(1);
19+
>a : Symbol(a, Decl(typeofThisInMethodSignature.ts, 7, 5))
20+
>new A().a : Symbol(A.a, Decl(typeofThisInMethodSignature.ts, 3, 6))
21+
>A : Symbol(A, Decl(typeofThisInMethodSignature.ts, 0, 0))
22+
>a : Symbol(A.a, Decl(typeofThisInMethodSignature.ts, 3, 6))
23+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/typeofThisInMethodSignature.ts ===
2+
// Repro from #54167
3+
4+
export class A {
5+
>A : A
6+
7+
x = 1
8+
>x : number
9+
>1 : 1
10+
11+
a(x: typeof this.x): void {}
12+
>a : (x: typeof this.x) => void
13+
>x : number
14+
>this.x : number
15+
>this : this
16+
>x : number
17+
}
18+
19+
const a = new A().a(1);
20+
>a : void
21+
>new A().a(1) : void
22+
>new A().a : (x: number) => void
23+
>new A() : A
24+
>A : typeof A
25+
>a : (x: number) => void
26+
>1 : 1
27+
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// @strict: true
2+
// @noEmit: true
3+
4+
// Repro from #54167
5+
6+
export class A {
7+
x = 1
8+
a(x: typeof this.x): void {}
9+
}
10+
11+
const a = new A().a(1);

0 commit comments

Comments
 (0)