mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Treat this as a constant reference for purpose of narrowing using aliased expressions (#54347)
This commit is contained in:
parent
d49a28534a
commit
2fb0267630
@ -26457,6 +26457,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
|
||||
function isConstantReference(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ThisKeyword:
|
||||
return true;
|
||||
case SyntaxKind.Identifier:
|
||||
if (!isThisInTypeQuery(node)) {
|
||||
const symbol = getResolvedSymbol(node as Identifier);
|
||||
|
||||
@ -22,17 +22,13 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(154,19): error TS2339
|
||||
Property 'foo' does not exist on type '{ kind: "bar"; bar: number; }'.
|
||||
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; }'.
|
||||
Property 'bar' does not exist on type '{ kind: "foo"; foo: string; }'.
|
||||
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(219,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(232,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(233,13): error TS2322: Type 'string | number' is not assignable to type 'string'.
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(280,5): error TS2448: Block-scoped variable 'a' used before its declaration.
|
||||
tests/cases/conformance/controlFlow/controlFlowAliasing.ts(280,5): error TS2454: Variable 'a' is used before being assigned.
|
||||
|
||||
|
||||
==== tests/cases/conformance/controlFlow/controlFlowAliasing.ts (17 errors) ====
|
||||
==== tests/cases/conformance/controlFlow/controlFlowAliasing.ts (15 errors) ====
|
||||
// Narrowing by aliased conditional expressions
|
||||
|
||||
function f10(x: string | number) {
|
||||
@ -288,9 +284,6 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(280,5): error TS2454:
|
||||
if (thisX_isString && xIsString) {
|
||||
let s: string;
|
||||
s = this.x;
|
||||
~
|
||||
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
s = x;
|
||||
}
|
||||
}
|
||||
@ -304,9 +297,6 @@ tests/cases/conformance/controlFlow/controlFlowAliasing.ts(280,5): error TS2454:
|
||||
// Some narrowings may be invalidated due to later assignments.
|
||||
let s: string;
|
||||
s = this.x;
|
||||
~
|
||||
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
|
||||
!!! error TS2322: Type 'number' is not assignable to type 'string'.
|
||||
s = x;
|
||||
~
|
||||
!!! 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:
|
||||
!!! error TS2454: Variable 'a' is used before being assigned.
|
||||
|
||||
const a = obj.fn();
|
||||
|
||||
|
||||
// repro from https://github.com/microsoft/TypeScript/issues/53267
|
||||
class Utils {
|
||||
static isDefined<T>(value: T): value is NonNullable<T> {
|
||||
return value != null;
|
||||
}
|
||||
}
|
||||
|
||||
class A53267 {
|
||||
public readonly testNumber: number | undefined;
|
||||
|
||||
foo() {
|
||||
const isNumber = Utils.isDefined(this.testNumber);
|
||||
|
||||
if (isNumber) {
|
||||
const x: number = this.testNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -281,7 +281,25 @@ const obj = {
|
||||
if (a) { }
|
||||
|
||||
const a = obj.fn();
|
||||
|
||||
|
||||
// repro from https://github.com/microsoft/TypeScript/issues/53267
|
||||
class Utils {
|
||||
static isDefined<T>(value: T): value is NonNullable<T> {
|
||||
return value != null;
|
||||
}
|
||||
}
|
||||
|
||||
class A53267 {
|
||||
public readonly testNumber: number | undefined;
|
||||
|
||||
foo() {
|
||||
const isNumber = Utils.isDefined(this.testNumber);
|
||||
|
||||
if (isNumber) {
|
||||
const x: number = this.testNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [controlFlowAliasing.js]
|
||||
"use strict";
|
||||
@ -538,6 +556,26 @@ var obj = {
|
||||
};
|
||||
if (a) { }
|
||||
var a = obj.fn();
|
||||
// repro from https://github.com/microsoft/TypeScript/issues/53267
|
||||
var Utils = /** @class */ (function () {
|
||||
function Utils() {
|
||||
}
|
||||
Utils.isDefined = function (value) {
|
||||
return value != null;
|
||||
};
|
||||
return Utils;
|
||||
}());
|
||||
var A53267 = /** @class */ (function () {
|
||||
function A53267() {
|
||||
}
|
||||
A53267.prototype.foo = function () {
|
||||
var isNumber = Utils.isDefined(this.testNumber);
|
||||
if (isNumber) {
|
||||
var x = this.testNumber;
|
||||
}
|
||||
};
|
||||
return A53267;
|
||||
}());
|
||||
|
||||
|
||||
//// [controlFlowAliasing.d.ts]
|
||||
@ -677,3 +715,10 @@ declare const obj: {
|
||||
fn: () => boolean;
|
||||
};
|
||||
declare const a: boolean;
|
||||
declare class Utils {
|
||||
static isDefined<T>(value: T): value is NonNullable<T>;
|
||||
}
|
||||
declare class A53267 {
|
||||
readonly testNumber: number | undefined;
|
||||
foo(): void;
|
||||
}
|
||||
|
||||
@ -791,3 +791,50 @@ const a = obj.fn();
|
||||
>obj : Symbol(obj, Decl(controlFlowAliasing.ts, 275, 5))
|
||||
>fn : Symbol(fn, Decl(controlFlowAliasing.ts, 275, 13))
|
||||
|
||||
// repro from https://github.com/microsoft/TypeScript/issues/53267
|
||||
class Utils {
|
||||
>Utils : Symbol(Utils, Decl(controlFlowAliasing.ts, 281, 19))
|
||||
|
||||
static isDefined<T>(value: T): value is NonNullable<T> {
|
||||
>isDefined : Symbol(Utils.isDefined, Decl(controlFlowAliasing.ts, 284, 13))
|
||||
>T : Symbol(T, Decl(controlFlowAliasing.ts, 285, 19))
|
||||
>value : Symbol(value, Decl(controlFlowAliasing.ts, 285, 22))
|
||||
>T : Symbol(T, Decl(controlFlowAliasing.ts, 285, 19))
|
||||
>value : Symbol(value, Decl(controlFlowAliasing.ts, 285, 22))
|
||||
>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(controlFlowAliasing.ts, 285, 19))
|
||||
|
||||
return value != null;
|
||||
>value : Symbol(value, Decl(controlFlowAliasing.ts, 285, 22))
|
||||
}
|
||||
}
|
||||
|
||||
class A53267 {
|
||||
>A53267 : Symbol(A53267, Decl(controlFlowAliasing.ts, 288, 1))
|
||||
|
||||
public readonly testNumber: number | undefined;
|
||||
>testNumber : Symbol(A53267.testNumber, Decl(controlFlowAliasing.ts, 290, 14))
|
||||
|
||||
foo() {
|
||||
>foo : Symbol(A53267.foo, Decl(controlFlowAliasing.ts, 291, 49))
|
||||
|
||||
const isNumber = Utils.isDefined(this.testNumber);
|
||||
>isNumber : Symbol(isNumber, Decl(controlFlowAliasing.ts, 294, 9))
|
||||
>Utils.isDefined : Symbol(Utils.isDefined, Decl(controlFlowAliasing.ts, 284, 13))
|
||||
>Utils : Symbol(Utils, Decl(controlFlowAliasing.ts, 281, 19))
|
||||
>isDefined : Symbol(Utils.isDefined, Decl(controlFlowAliasing.ts, 284, 13))
|
||||
>this.testNumber : Symbol(A53267.testNumber, Decl(controlFlowAliasing.ts, 290, 14))
|
||||
>this : Symbol(A53267, Decl(controlFlowAliasing.ts, 288, 1))
|
||||
>testNumber : Symbol(A53267.testNumber, Decl(controlFlowAliasing.ts, 290, 14))
|
||||
|
||||
if (isNumber) {
|
||||
>isNumber : Symbol(isNumber, Decl(controlFlowAliasing.ts, 294, 9))
|
||||
|
||||
const x: number = this.testNumber;
|
||||
>x : Symbol(x, Decl(controlFlowAliasing.ts, 297, 11))
|
||||
>this.testNumber : Symbol(A53267.testNumber, Decl(controlFlowAliasing.ts, 290, 14))
|
||||
>this : Symbol(A53267, Decl(controlFlowAliasing.ts, 288, 1))
|
||||
>testNumber : Symbol(A53267.testNumber, Decl(controlFlowAliasing.ts, 290, 14))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -731,11 +731,11 @@ class C10 {
|
||||
>s : string
|
||||
|
||||
s = this.x;
|
||||
>s = this.x : string | number
|
||||
>s = this.x : string
|
||||
>s : string
|
||||
>this.x : string | number
|
||||
>this.x : string
|
||||
>this : this
|
||||
>x : string | number
|
||||
>x : string
|
||||
|
||||
s = x;
|
||||
>s = x : string
|
||||
@ -777,11 +777,11 @@ class C11 {
|
||||
>s : string
|
||||
|
||||
s = this.x;
|
||||
>s = this.x : string | number
|
||||
>s = this.x : string
|
||||
>s : string
|
||||
>this.x : string | number
|
||||
>this.x : string
|
||||
>this : this
|
||||
>x : string | number
|
||||
>x : string
|
||||
|
||||
s = x;
|
||||
>s = x : string | number
|
||||
@ -918,3 +918,47 @@ const a = obj.fn();
|
||||
>obj : { fn: () => boolean; }
|
||||
>fn : () => boolean
|
||||
|
||||
// repro from https://github.com/microsoft/TypeScript/issues/53267
|
||||
class Utils {
|
||||
>Utils : Utils
|
||||
|
||||
static isDefined<T>(value: T): value is NonNullable<T> {
|
||||
>isDefined : <T>(value: T) => value is NonNullable<T>
|
||||
>value : T
|
||||
|
||||
return value != null;
|
||||
>value != null : boolean
|
||||
>value : T
|
||||
}
|
||||
}
|
||||
|
||||
class A53267 {
|
||||
>A53267 : A53267
|
||||
|
||||
public readonly testNumber: number | undefined;
|
||||
>testNumber : number | undefined
|
||||
|
||||
foo() {
|
||||
>foo : () => void
|
||||
|
||||
const isNumber = Utils.isDefined(this.testNumber);
|
||||
>isNumber : boolean
|
||||
>Utils.isDefined(this.testNumber) : boolean
|
||||
>Utils.isDefined : <T>(value: T) => value is NonNullable<T>
|
||||
>Utils : typeof Utils
|
||||
>isDefined : <T>(value: T) => value is NonNullable<T>
|
||||
>this.testNumber : number | undefined
|
||||
>this : this
|
||||
>testNumber : number | undefined
|
||||
|
||||
if (isNumber) {
|
||||
>isNumber : boolean
|
||||
|
||||
const x: number = this.testNumber;
|
||||
>x : number
|
||||
>this.testNumber : number
|
||||
>this : this
|
||||
>testNumber : number
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,3 +283,22 @@ const obj = {
|
||||
if (a) { }
|
||||
|
||||
const a = obj.fn();
|
||||
|
||||
// repro from https://github.com/microsoft/TypeScript/issues/53267
|
||||
class Utils {
|
||||
static isDefined<T>(value: T): value is NonNullable<T> {
|
||||
return value != null;
|
||||
}
|
||||
}
|
||||
|
||||
class A53267 {
|
||||
public readonly testNumber: number | undefined;
|
||||
|
||||
foo() {
|
||||
const isNumber = Utils.isDefined(this.testNumber);
|
||||
|
||||
if (isNumber) {
|
||||
const x: number = this.testNumber;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user