From 8a68c8616d20dd2930fd9a5ade33178443799d15 Mon Sep 17 00:00:00 2001 From: Zzzen Date: Thu, 28 Oct 2021 01:26:05 +0800 Subject: [PATCH] allow `typeof this` after for-loops (#46181) --- src/compiler/checker.ts | 7 ++- .../baselines/reference/typeofThis.errors.txt | 21 +++++++++ tests/baselines/reference/typeofThis.js | 39 ++++++++++++++++ tests/baselines/reference/typeofThis.symbols | 39 ++++++++++++++++ tests/baselines/reference/typeofThis.types | 45 +++++++++++++++++++ .../specifyingTypes/typeQueries/typeofThis.ts | 21 +++++++++ 6 files changed, 170 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a33f986723..65998566d1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22496,8 +22496,11 @@ namespace ts { function getFlowCacheKey(node: Node, declaredType: Type, initialType: Type, flowContainer: Node | undefined): string | undefined { switch (node.kind) { case SyntaxKind.Identifier: - const symbol = getResolvedSymbol(node as Identifier); - return symbol !== unknownSymbol ? `${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${getTypeId(initialType)}|${getSymbolId(symbol)}` : undefined; + if (!isThisInTypeQuery(node)) { + const symbol = getResolvedSymbol(node as Identifier); + return symbol !== unknownSymbol ? `${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${getTypeId(initialType)}|${getSymbolId(symbol)}` : undefined; + } + // falls through case SyntaxKind.ThisKeyword: return `0|${flowContainer ? getNodeId(flowContainer) : "-1"}|${getTypeId(declaredType)}|${getTypeId(initialType)}`; case SyntaxKind.NonNullExpression: diff --git a/tests/baselines/reference/typeofThis.errors.txt b/tests/baselines/reference/typeofThis.errors.txt index 0859ccaa2d..a4a3be693a 100644 --- a/tests/baselines/reference/typeofThis.errors.txt +++ b/tests/baselines/reference/typeofThis.errors.txt @@ -146,4 +146,25 @@ tests/cases/conformance/types/specifyingTypes/typeQueries/typeofThis.ts(57,24): let y: string = o.this.x; // should narrow to string } } + } + + class Tests12 { + test1() { // OK + type Test = typeof this; + } + + test2() { // OK + for (;;) {} + type Test = typeof this; + } + + test3() { // expected no compile errors + for (const dummy in []) {} + type Test = typeof this; + } + + test4() { // expected no compile errors + for (const dummy of []) {} + type Test = typeof this; + } } \ No newline at end of file diff --git a/tests/baselines/reference/typeofThis.js b/tests/baselines/reference/typeofThis.js index e06e3e383f..4de9aac427 100644 --- a/tests/baselines/reference/typeofThis.js +++ b/tests/baselines/reference/typeofThis.js @@ -120,6 +120,27 @@ class Test11 { let y: string = o.this.x; // should narrow to string } } +} + +class Tests12 { + test1() { // OK + type Test = typeof this; + } + + test2() { // OK + for (;;) {} + type Test = typeof this; + } + + test3() { // expected no compile errors + for (const dummy in []) {} + type Test = typeof this; + } + + test4() { // expected no compile errors + for (const dummy of []) {} + type Test = typeof this; + } } //// [typeofThis.js] @@ -241,3 +262,21 @@ var Test11 = /** @class */ (function () { }; return Test11; }()); +var Tests12 = /** @class */ (function () { + function Tests12() { + } + Tests12.prototype.test1 = function () { + }; + Tests12.prototype.test2 = function () { + for (;;) { } + }; + Tests12.prototype.test3 = function () { + for (var dummy in []) { } + }; + Tests12.prototype.test4 = function () { + for (var _i = 0, _a = []; _i < _a.length; _i++) { + var dummy = _a[_i]; + } + }; + return Tests12; +}()); diff --git a/tests/baselines/reference/typeofThis.symbols b/tests/baselines/reference/typeofThis.symbols index dde439e3d0..5314551f51 100644 --- a/tests/baselines/reference/typeofThis.symbols +++ b/tests/baselines/reference/typeofThis.symbols @@ -312,3 +312,42 @@ class Test11 { } } } + +class Tests12 { +>Tests12 : Symbol(Tests12, Decl(typeofThis.ts, 121, 1)) + + test1() { // OK +>test1 : Symbol(Tests12.test1, Decl(typeofThis.ts, 123, 15)) + + type Test = typeof this; +>Test : Symbol(Test, Decl(typeofThis.ts, 124, 13)) + } + + test2() { // OK +>test2 : Symbol(Tests12.test2, Decl(typeofThis.ts, 126, 5)) + + for (;;) {} + type Test = typeof this; +>Test : Symbol(Test, Decl(typeofThis.ts, 129, 19)) + } + + test3() { // expected no compile errors +>test3 : Symbol(Tests12.test3, Decl(typeofThis.ts, 131, 5)) + + for (const dummy in []) {} +>dummy : Symbol(dummy, Decl(typeofThis.ts, 134, 18)) + + type Test = typeof this; +>Test : Symbol(Test, Decl(typeofThis.ts, 134, 34)) + } + + test4() { // expected no compile errors +>test4 : Symbol(Tests12.test4, Decl(typeofThis.ts, 136, 5)) + + for (const dummy of []) {} +>dummy : Symbol(dummy, Decl(typeofThis.ts, 139, 18)) + + type Test = typeof this; +>Test : Symbol(Test, Decl(typeofThis.ts, 139, 34)) + } +} diff --git a/tests/baselines/reference/typeofThis.types b/tests/baselines/reference/typeofThis.types index 61d8c8080e..5234d97282 100644 --- a/tests/baselines/reference/typeofThis.types +++ b/tests/baselines/reference/typeofThis.types @@ -377,3 +377,48 @@ class Test11 { } } } + +class Tests12 { +>Tests12 : Tests12 + + test1() { // OK +>test1 : () => void + + type Test = typeof this; +>Test : this +>this : any + } + + test2() { // OK +>test2 : () => void + + for (;;) {} + type Test = typeof this; +>Test : this +>this : any + } + + test3() { // expected no compile errors +>test3 : () => void + + for (const dummy in []) {} +>dummy : string +>[] : never[] + + type Test = typeof this; +>Test : this +>this : any + } + + test4() { // expected no compile errors +>test4 : () => void + + for (const dummy of []) {} +>dummy : never +>[] : never[] + + type Test = typeof this; +>Test : this +>this : any + } +} diff --git a/tests/cases/conformance/types/specifyingTypes/typeQueries/typeofThis.ts b/tests/cases/conformance/types/specifyingTypes/typeQueries/typeofThis.ts index 78eb779147..420604c550 100644 --- a/tests/cases/conformance/types/specifyingTypes/typeQueries/typeofThis.ts +++ b/tests/cases/conformance/types/specifyingTypes/typeQueries/typeofThis.ts @@ -122,4 +122,25 @@ class Test11 { let y: string = o.this.x; // should narrow to string } } +} + +class Tests12 { + test1() { // OK + type Test = typeof this; + } + + test2() { // OK + for (;;) {} + type Test = typeof this; + } + + test3() { // expected no compile errors + for (const dummy in []) {} + type Test = typeof this; + } + + test4() { // expected no compile errors + for (const dummy of []) {} + type Test = typeof this; + } } \ No newline at end of file