Skip to content

Commit c6ebde7

Browse files
committed
Treat this as a constant reference for purpose of narrowing using aliased expressions
1 parent 174599c commit c6ebde7

File tree

6 files changed

+184
-19
lines changed

6 files changed

+184
-19
lines changed

src/compiler/checker.ts

+2
Original file line numberDiff line numberDiff line change
@@ -26458,6 +26458,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2645826458

2645926459
function isConstantReference(node: Node): boolean {
2646026460
switch (node.kind) {
26461+
case SyntaxKind.ThisKeyword:
26462+
return true;
2646126463
case SyntaxKind.Identifier:
2646226464
if (!isThisInTypeQuery(node)) {
2646326465
const symbol = getResolvedSymbol(node as Identifier);

tests/baselines/reference/controlFlowAliasing.errors.txt

+20-12
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,13 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(154,19): error TS2339
2222
Property 'foo' does not exist on type '{ kind: "bar"; bar: number; }'.
2323
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(157,19): error TS2339: Property 'bar' does not exist on type '{ kind: "foo"; foo: string; } | { kind: "bar"; bar: number; }'.
2424
Property 'bar' does not exist on type '{ kind: "foo"; foo: string; }'.
25-
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(219,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
26-
Type 'number' is not assignable to type 'string'.
27-
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(232,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
28-
Type 'number' is not assignable to type 'string'.
2925
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(233,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
3026
Type 'number' is not assignable to type 'string'.
3127
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(280,5): error TS2448: Block-scoped variable 'a' used before its declaration.
3228
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(280,5): error TS2454: Variable 'a' is used before being assigned.
3329

3430

35-
==== tests/cases/conformance/controlFlow/controlFlowAliasing.ts (17 errors) ====
31+
==== tests/cases/conformance/controlFlow/controlFlowAliasing.ts (15 errors) ====
3632
// Narrowing by aliased conditional expressions
3733

3834
function f10(x: string | number) {
@@ -288,9 +284,6 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(280,5): error TS2454:
288284
if (thisX_isString && xIsString) {
289285
let s: string;
290286
s = this.x;
291-
~
292-
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
293-
!!! error TS2322: Type 'number' is not assignable to type 'string'.
294287
s = x;
295288
}
296289
}
@@ -304,9 +297,6 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(280,5): error TS2454:
304297
// Some narrowings may be invalidated due to later assignments.
305298
let s: string;
306299
s = this.x;
307-
~
308-
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
309-
!!! error TS2322: Type 'number' is not assignable to type 'string'.
310300
s = x;
311301
~
312302
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
@@ -365,4 +355,22 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(280,5): error TS2454:
365355
!!! error TS2454: Variable 'a' is used before being assigned.
366356

367357
const a = obj.fn();
368-
358+
359+
// repro from https://github.com/microsoft/TypeScript/issues/53267
360+
class Utils {
361+
static isDefined<T>(value: T): value is NonNullable<T> {
362+
return value != null;
363+
}
364+
}
365+
366+
class A53267 {
367+
public readonly testNumber: number | undefined;
368+
369+
foo() {
370+
const isNumber = Utils.isDefined(this.testNumber);
371+
372+
if (isNumber) {
373+
const x: number = this.testNumber;
374+
}
375+
}
376+
}

tests/baselines/reference/controlFlowAliasing.js

+46-1
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,25 @@ const obj = {
281281
if (a) { }
282282

283283
const a = obj.fn();
284-
284+
285+
// repro from https://github.com/microsoft/TypeScript/issues/53267
286+
class Utils {
287+
static isDefined<T>(value: T): value is NonNullable<T> {
288+
return value != null;
289+
}
290+
}
291+
292+
class A53267 {
293+
public readonly testNumber: number | undefined;
294+
295+
foo() {
296+
const isNumber = Utils.isDefined(this.testNumber);
297+
298+
if (isNumber) {
299+
const x: number = this.testNumber;
300+
}
301+
}
302+
}
285303

286304
//// [controlFlowAliasing.js]
287305
"use strict";
@@ -538,6 +556,26 @@ var obj = {
538556
};
539557
if (a) { }
540558
var a = obj.fn();
559+
// repro from https://github.com/microsoft/TypeScript/issues/53267
560+
var Utils = /** @class */ (function () {
561+
function Utils() {
562+
}
563+
Utils.isDefined = function (value) {
564+
return value != null;
565+
};
566+
return Utils;
567+
}());
568+
var A53267 = /** @class */ (function () {
569+
function A53267() {
570+
}
571+
A53267.prototype.foo = function () {
572+
var isNumber = Utils.isDefined(this.testNumber);
573+
if (isNumber) {
574+
var x = this.testNumber;
575+
}
576+
};
577+
return A53267;
578+
}());
541579

542580

543581
//// [controlFlowAliasing.d.ts]
@@ -677,3 +715,10 @@ declare const obj: {
677715
fn: () => boolean;
678716
};
679717
declare const a: boolean;
718+
declare class Utils {
719+
static isDefined<T>(value: T): value is NonNullable<T>;
720+
}
721+
declare class A53267 {
722+
readonly testNumber: number | undefined;
723+
foo(): void;
724+
}

tests/baselines/reference/controlFlowAliasing.symbols

+47
Original file line numberDiff line numberDiff line change
@@ -791,3 +791,50 @@ const a = obj.fn();
791791
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 275, 5))
792792
>fn : Symbol(fn, Decl(controlFlowAliasing.ts, 275, 13))
793793

794+
// repro from https://github.com/microsoft/TypeScript/issues/53267
795+
class Utils {
796+
>Utils : Symbol(Utils, Decl(controlFlowAliasing.ts, 281, 19))
797+
798+
static isDefined<T>(value: T): value is NonNullable<T> {
799+
>isDefined : Symbol(Utils.isDefined, Decl(controlFlowAliasing.ts, 284, 13))
800+
>T : Symbol(T, Decl(controlFlowAliasing.ts, 285, 19))
801+
>value : Symbol(value, Decl(controlFlowAliasing.ts, 285, 22))
802+
>T : Symbol(T, Decl(controlFlowAliasing.ts, 285, 19))
803+
>value : Symbol(value, Decl(controlFlowAliasing.ts, 285, 22))
804+
>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --))
805+
>T : Symbol(T, Decl(controlFlowAliasing.ts, 285, 19))
806+
807+
return value != null;
808+
>value : Symbol(value, Decl(controlFlowAliasing.ts, 285, 22))
809+
}
810+
}
811+
812+
class A53267 {
813+
>A53267 : Symbol(A53267, Decl(controlFlowAliasing.ts, 288, 1))
814+
815+
public readonly testNumber: number | undefined;
816+
>testNumber : Symbol(A53267.testNumber, Decl(controlFlowAliasing.ts, 290, 14))
817+
818+
foo() {
819+
>foo : Symbol(A53267.foo, Decl(controlFlowAliasing.ts, 291, 49))
820+
821+
const isNumber = Utils.isDefined(this.testNumber);
822+
>isNumber : Symbol(isNumber, Decl(controlFlowAliasing.ts, 294, 9))
823+
>Utils.isDefined : Symbol(Utils.isDefined, Decl(controlFlowAliasing.ts, 284, 13))
824+
>Utils : Symbol(Utils, Decl(controlFlowAliasing.ts, 281, 19))
825+
>isDefined : Symbol(Utils.isDefined, Decl(controlFlowAliasing.ts, 284, 13))
826+
>this.testNumber : Symbol(A53267.testNumber, Decl(controlFlowAliasing.ts, 290, 14))
827+
>this : Symbol(A53267, Decl(controlFlowAliasing.ts, 288, 1))
828+
>testNumber : Symbol(A53267.testNumber, Decl(controlFlowAliasing.ts, 290, 14))
829+
830+
if (isNumber) {
831+
>isNumber : Symbol(isNumber, Decl(controlFlowAliasing.ts, 294, 9))
832+
833+
const x: number = this.testNumber;
834+
>x : Symbol(x, Decl(controlFlowAliasing.ts, 297, 11))
835+
>this.testNumber : Symbol(A53267.testNumber, Decl(controlFlowAliasing.ts, 290, 14))
836+
>this : Symbol(A53267, Decl(controlFlowAliasing.ts, 288, 1))
837+
>testNumber : Symbol(A53267.testNumber, Decl(controlFlowAliasing.ts, 290, 14))
838+
}
839+
}
840+
}

tests/baselines/reference/controlFlowAliasing.types

+50-6
Original file line numberDiff line numberDiff line change
@@ -731,11 +731,11 @@ class C10 {
731731
>s : string
732732

733733
s = this.x;
734-
>s = this.x : string | number
734+
>s = this.x : string
735735
>s : string
736-
>this.x : string | number
736+
>this.x : string
737737
>this : this
738-
>x : string | number
738+
>x : string
739739

740740
s = x;
741741
>s = x : string
@@ -777,11 +777,11 @@ class C11 {
777777
>s : string
778778

779779
s = this.x;
780-
>s = this.x : string | number
780+
>s = this.x : string
781781
>s : string
782-
>this.x : string | number
782+
>this.x : string
783783
>this : this
784-
>x : string | number
784+
>x : string
785785

786786
s = x;
787787
>s = x : string | number
@@ -918,3 +918,47 @@ const a = obj.fn();
918918
>obj : { fn: () => boolean; }
919919
>fn : () => boolean
920920

921+
// repro from https://github.com/microsoft/TypeScript/issues/53267
922+
class Utils {
923+
>Utils : Utils
924+
925+
static isDefined<T>(value: T): value is NonNullable<T> {
926+
>isDefined : <T>(value: T) => value is NonNullable<T>
927+
>value : T
928+
929+
return value != null;
930+
>value != null : boolean
931+
>value : T
932+
}
933+
}
934+
935+
class A53267 {
936+
>A53267 : A53267
937+
938+
public readonly testNumber: number | undefined;
939+
>testNumber : number | undefined
940+
941+
foo() {
942+
>foo : () => void
943+
944+
const isNumber = Utils.isDefined(this.testNumber);
945+
>isNumber : boolean
946+
>Utils.isDefined(this.testNumber) : boolean
947+
>Utils.isDefined : <T>(value: T) => value is NonNullable<T>
948+
>Utils : typeof Utils
949+
>isDefined : <T>(value: T) => value is NonNullable<T>
950+
>this.testNumber : number | undefined
951+
>this : this
952+
>testNumber : number | undefined
953+
954+
if (isNumber) {
955+
>isNumber : boolean
956+
957+
const x: number = this.testNumber;
958+
>x : number
959+
>this.testNumber : number
960+
>this : this
961+
>testNumber : number
962+
}
963+
}
964+
}

tests/cases/conformance/controlFlow/controlFlowAliasing.ts

+19
Original file line numberDiff line numberDiff line change
@@ -283,3 +283,22 @@ const obj = {
283283
if (a) { }
284284

285285
const a = obj.fn();
286+
287+
// repro from https://github.com/microsoft/TypeScript/issues/53267
288+
class Utils {
289+
static isDefined<T>(value: T): value is NonNullable<T> {
290+
return value != null;
291+
}
292+
}
293+
294+
class A53267 {
295+
public readonly testNumber: number | undefined;
296+
297+
foo() {
298+
const isNumber = Utils.isDefined(this.testNumber);
299+
300+
if (isNumber) {
301+
const x: number = this.testNumber;
302+
}
303+
}
304+
}

0 commit comments

Comments
 (0)