🤖 Pick PR #54208 (Properly handle typeof this.xxx i...) into release-5.1 (#54413)

Co-authored-by: Anders Hejlsberg <andersh@microsoft.com>
This commit is contained in:
TypeScript Bot
2023-05-29 12:51:54 -07:00
committed by GitHub
co-authored by Anders Hejlsberg
parent 42e783930e
commit 898edb5381
4 changed files with 71 additions and 19 deletions
+10 -19
View File
@@ -18813,25 +18813,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
case SyntaxKind.TypeQuery:
const entityName = (node as TypeQueryNode).exprName;
const firstIdentifier = getFirstIdentifier(entityName);
const firstIdentifierSymbol = getResolvedSymbol(firstIdentifier);
const tpDeclaration = tp.symbol.declarations![0]; // There is exactly one declaration, otherwise `containsReference` is not called
let tpScope: Node;
if (tpDeclaration.kind === SyntaxKind.TypeParameter) { // Type parameter is a regular type parameter, e.g. foo<T>
tpScope = tpDeclaration.parent;
}
else if (tp.isThisType) {
// Type parameter is the this type, and its declaration is the class declaration.
tpScope = tpDeclaration;
}
else {
// Type parameter's declaration was unrecognized.
// This could happen if the type parameter comes from e.g. a JSDoc annotation, so we default to returning true.
return true;
}
if (firstIdentifierSymbol.declarations) {
return some(firstIdentifierSymbol.declarations, idDecl => isNodeDescendantOf(idDecl, tpScope)) ||
some((node as TypeQueryNode).typeArguments, containsReference);
if (!isThisIdentifier(firstIdentifier)) { // Don't attempt to analyze typeof this.xxx
const firstIdentifierSymbol = getResolvedSymbol(firstIdentifier);
const tpDeclaration = tp.symbol.declarations![0]; // There is exactly one declaration, otherwise `containsReference` is not called
const tpScope = tpDeclaration.kind === SyntaxKind.TypeParameter ? tpDeclaration.parent : // Type parameter is a regular type parameter, e.g. foo<T>
tp.isThisType ? tpDeclaration : // Type parameter is the this type, and its declaration is the class declaration.
undefined; // Type parameter's declaration was unrecognized, e.g. comes from JSDoc annotation.
if (firstIdentifierSymbol.declarations && tpScope) {
return some(firstIdentifierSymbol.declarations, idDecl => isNodeDescendantOf(idDecl, tpScope)) ||
some((node as TypeQueryNode).typeArguments, containsReference);
}
}
return true;
case SyntaxKind.MethodDeclaration:
@@ -0,0 +1,23 @@
=== tests/cases/compiler/typeofThisInMethodSignature.ts ===
// Repro from #54167
export class A {
>A : Symbol(A, Decl(typeofThisInMethodSignature.ts, 0, 0))
x = 1
>x : Symbol(A.x, Decl(typeofThisInMethodSignature.ts, 2, 16))
a(x: typeof this.x): void {}
>a : Symbol(A.a, Decl(typeofThisInMethodSignature.ts, 3, 6))
>x : Symbol(x, Decl(typeofThisInMethodSignature.ts, 4, 3))
>this.x : Symbol(A.x, Decl(typeofThisInMethodSignature.ts, 2, 16))
>this : Symbol(A, Decl(typeofThisInMethodSignature.ts, 0, 0))
>x : Symbol(A.x, Decl(typeofThisInMethodSignature.ts, 2, 16))
}
const a = new A().a(1);
>a : Symbol(a, Decl(typeofThisInMethodSignature.ts, 7, 5))
>new A().a : Symbol(A.a, Decl(typeofThisInMethodSignature.ts, 3, 6))
>A : Symbol(A, Decl(typeofThisInMethodSignature.ts, 0, 0))
>a : Symbol(A.a, Decl(typeofThisInMethodSignature.ts, 3, 6))
@@ -0,0 +1,27 @@
=== tests/cases/compiler/typeofThisInMethodSignature.ts ===
// Repro from #54167
export class A {
>A : A
x = 1
>x : number
>1 : 1
a(x: typeof this.x): void {}
>a : (x: typeof this.x) => void
>x : number
>this.x : number
>this : this
>x : number
}
const a = new A().a(1);
>a : void
>new A().a(1) : void
>new A().a : (x: number) => void
>new A() : A
>A : typeof A
>a : (x: number) => void
>1 : 1
@@ -0,0 +1,11 @@
// @strict: true
// @noEmit: true
// Repro from #54167
export class A {
x = 1
a(x: typeof this.x): void {}
}
const a = new A().a(1);