mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-06 04:35:21 -05:00
Chain RHS narrowing and truthiness narrowing in assignment expression narrowing (#31348)
This commit is contained in:
@@ -16773,7 +16773,7 @@ namespace ts {
|
||||
function narrowTypeByBinaryExpression(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type {
|
||||
switch (expr.operatorToken.kind) {
|
||||
case SyntaxKind.EqualsToken:
|
||||
return narrowTypeByTruthiness(type, expr.left, assumeTrue);
|
||||
return narrowTypeByTruthiness(narrowType(type, expr.right, assumeTrue), expr.left, assumeTrue);
|
||||
case SyntaxKind.EqualsEqualsToken:
|
||||
case SyntaxKind.ExclamationEqualsToken:
|
||||
case SyntaxKind.EqualsEqualsEqualsToken:
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
//// [controlFlowForCompoundAssignmentToThisMember.ts]
|
||||
class DatasourceCommandWidgetElement {
|
||||
_commandBased: boolean;
|
||||
_commandElement: unknown;
|
||||
commandElement: unknown;
|
||||
|
||||
constructor(target: unknown) {
|
||||
if (target instanceof DatasourceCommandWidgetElement) {
|
||||
this._commandBased = true;
|
||||
this._commandElement = target.commandElement;
|
||||
} else {
|
||||
this._commandBased = false;
|
||||
}
|
||||
|
||||
if (this._commandBased = (target instanceof DatasourceCommandWidgetElement)) {
|
||||
this._commandElement = target.commandElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// [controlFlowForCompoundAssignmentToThisMember.js]
|
||||
var DatasourceCommandWidgetElement = /** @class */ (function () {
|
||||
function DatasourceCommandWidgetElement(target) {
|
||||
if (target instanceof DatasourceCommandWidgetElement) {
|
||||
this._commandBased = true;
|
||||
this._commandElement = target.commandElement;
|
||||
}
|
||||
else {
|
||||
this._commandBased = false;
|
||||
}
|
||||
if (this._commandBased = (target instanceof DatasourceCommandWidgetElement)) {
|
||||
this._commandElement = target.commandElement;
|
||||
}
|
||||
}
|
||||
return DatasourceCommandWidgetElement;
|
||||
}());
|
||||
@@ -0,0 +1,57 @@
|
||||
=== tests/cases/compiler/controlFlowForCompoundAssignmentToThisMember.ts ===
|
||||
class DatasourceCommandWidgetElement {
|
||||
>DatasourceCommandWidgetElement : Symbol(DatasourceCommandWidgetElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 0))
|
||||
|
||||
_commandBased: boolean;
|
||||
>_commandBased : Symbol(DatasourceCommandWidgetElement._commandBased, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 38))
|
||||
|
||||
_commandElement: unknown;
|
||||
>_commandElement : Symbol(DatasourceCommandWidgetElement._commandElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 1, 27))
|
||||
|
||||
commandElement: unknown;
|
||||
>commandElement : Symbol(DatasourceCommandWidgetElement.commandElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 2, 29))
|
||||
|
||||
constructor(target: unknown) {
|
||||
>target : Symbol(target, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 5, 16))
|
||||
|
||||
if (target instanceof DatasourceCommandWidgetElement) {
|
||||
>target : Symbol(target, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 5, 16))
|
||||
>DatasourceCommandWidgetElement : Symbol(DatasourceCommandWidgetElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 0))
|
||||
|
||||
this._commandBased = true;
|
||||
>this._commandBased : Symbol(DatasourceCommandWidgetElement._commandBased, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 38))
|
||||
>this : Symbol(DatasourceCommandWidgetElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 0))
|
||||
>_commandBased : Symbol(DatasourceCommandWidgetElement._commandBased, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 38))
|
||||
|
||||
this._commandElement = target.commandElement;
|
||||
>this._commandElement : Symbol(DatasourceCommandWidgetElement._commandElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 1, 27))
|
||||
>this : Symbol(DatasourceCommandWidgetElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 0))
|
||||
>_commandElement : Symbol(DatasourceCommandWidgetElement._commandElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 1, 27))
|
||||
>target.commandElement : Symbol(DatasourceCommandWidgetElement.commandElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 2, 29))
|
||||
>target : Symbol(target, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 5, 16))
|
||||
>commandElement : Symbol(DatasourceCommandWidgetElement.commandElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 2, 29))
|
||||
|
||||
} else {
|
||||
this._commandBased = false;
|
||||
>this._commandBased : Symbol(DatasourceCommandWidgetElement._commandBased, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 38))
|
||||
>this : Symbol(DatasourceCommandWidgetElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 0))
|
||||
>_commandBased : Symbol(DatasourceCommandWidgetElement._commandBased, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 38))
|
||||
}
|
||||
|
||||
if (this._commandBased = (target instanceof DatasourceCommandWidgetElement)) {
|
||||
>this._commandBased : Symbol(DatasourceCommandWidgetElement._commandBased, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 38))
|
||||
>this : Symbol(DatasourceCommandWidgetElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 0))
|
||||
>_commandBased : Symbol(DatasourceCommandWidgetElement._commandBased, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 38))
|
||||
>target : Symbol(target, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 5, 16))
|
||||
>DatasourceCommandWidgetElement : Symbol(DatasourceCommandWidgetElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 0))
|
||||
|
||||
this._commandElement = target.commandElement;
|
||||
>this._commandElement : Symbol(DatasourceCommandWidgetElement._commandElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 1, 27))
|
||||
>this : Symbol(DatasourceCommandWidgetElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 0, 0))
|
||||
>_commandElement : Symbol(DatasourceCommandWidgetElement._commandElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 1, 27))
|
||||
>target.commandElement : Symbol(DatasourceCommandWidgetElement.commandElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 2, 29))
|
||||
>target : Symbol(target, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 5, 16))
|
||||
>commandElement : Symbol(DatasourceCommandWidgetElement.commandElement, Decl(controlFlowForCompoundAssignmentToThisMember.ts, 2, 29))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
=== tests/cases/compiler/controlFlowForCompoundAssignmentToThisMember.ts ===
|
||||
class DatasourceCommandWidgetElement {
|
||||
>DatasourceCommandWidgetElement : DatasourceCommandWidgetElement
|
||||
|
||||
_commandBased: boolean;
|
||||
>_commandBased : boolean
|
||||
|
||||
_commandElement: unknown;
|
||||
>_commandElement : unknown
|
||||
|
||||
commandElement: unknown;
|
||||
>commandElement : unknown
|
||||
|
||||
constructor(target: unknown) {
|
||||
>target : unknown
|
||||
|
||||
if (target instanceof DatasourceCommandWidgetElement) {
|
||||
>target instanceof DatasourceCommandWidgetElement : boolean
|
||||
>target : unknown
|
||||
>DatasourceCommandWidgetElement : typeof DatasourceCommandWidgetElement
|
||||
|
||||
this._commandBased = true;
|
||||
>this._commandBased = true : true
|
||||
>this._commandBased : boolean
|
||||
>this : this
|
||||
>_commandBased : boolean
|
||||
>true : true
|
||||
|
||||
this._commandElement = target.commandElement;
|
||||
>this._commandElement = target.commandElement : unknown
|
||||
>this._commandElement : unknown
|
||||
>this : this
|
||||
>_commandElement : unknown
|
||||
>target.commandElement : unknown
|
||||
>target : DatasourceCommandWidgetElement
|
||||
>commandElement : unknown
|
||||
|
||||
} else {
|
||||
this._commandBased = false;
|
||||
>this._commandBased = false : false
|
||||
>this._commandBased : boolean
|
||||
>this : this
|
||||
>_commandBased : boolean
|
||||
>false : false
|
||||
}
|
||||
|
||||
if (this._commandBased = (target instanceof DatasourceCommandWidgetElement)) {
|
||||
>this._commandBased = (target instanceof DatasourceCommandWidgetElement) : boolean
|
||||
>this._commandBased : boolean
|
||||
>this : this
|
||||
>_commandBased : boolean
|
||||
>(target instanceof DatasourceCommandWidgetElement) : boolean
|
||||
>target instanceof DatasourceCommandWidgetElement : boolean
|
||||
>target : unknown
|
||||
>DatasourceCommandWidgetElement : typeof DatasourceCommandWidgetElement
|
||||
|
||||
this._commandElement = target.commandElement;
|
||||
>this._commandElement = target.commandElement : unknown
|
||||
>this._commandElement : unknown
|
||||
>this : this
|
||||
>_commandElement : unknown
|
||||
>target.commandElement : unknown
|
||||
>target : DatasourceCommandWidgetElement
|
||||
>commandElement : unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ function f5() {
|
||||
>x : string
|
||||
|
||||
y; // string | undefined
|
||||
>y : string | undefined
|
||||
>y : string
|
||||
}
|
||||
else {
|
||||
x; // string | undefined
|
||||
|
||||
@@ -211,11 +211,11 @@ function foo8(x: number | string | boolean) {
|
||||
>typeof x === "boolean" ? x // boolean : x == 10 : boolean
|
||||
>typeof x === "boolean" : boolean
|
||||
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>x : number | boolean
|
||||
>x : number | true
|
||||
>"boolean" : "boolean"
|
||||
|
||||
? x // boolean
|
||||
>x : boolean
|
||||
>x : true
|
||||
|
||||
: x == 10)); // boolean
|
||||
>x == 10 : boolean
|
||||
@@ -286,7 +286,7 @@ function foo10(x: number | string | boolean) {
|
||||
&& typeof x === "number"
|
||||
>typeof x === "number" : boolean
|
||||
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>x : number | boolean
|
||||
>x : number | true
|
||||
>"number" : "number"
|
||||
|
||||
&& x.toString()); // x is number
|
||||
@@ -326,7 +326,7 @@ function foo11(x: number | string | boolean) {
|
||||
&& typeof x === "number"
|
||||
>typeof x === "number" : boolean
|
||||
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>x : number | boolean
|
||||
>x : number | true
|
||||
>"number" : "number"
|
||||
|
||||
&& (x = 10) // assignment to x
|
||||
@@ -379,7 +379,7 @@ function foo12(x: number | string | boolean) {
|
||||
&& typeof x === "number"
|
||||
>typeof x === "number" : boolean
|
||||
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>x : number | boolean
|
||||
>x : number | true
|
||||
>"number" : "number"
|
||||
|
||||
&& x); // x is number
|
||||
|
||||
@@ -102,11 +102,11 @@ function foo5(x: number | string | boolean) {
|
||||
>typeof x !== "number" // number | boolean && x : boolean
|
||||
>typeof x !== "number" : boolean
|
||||
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>x : number | boolean
|
||||
>x : number | true
|
||||
>"number" : "number"
|
||||
|
||||
&& x)); // boolean
|
||||
>x : boolean
|
||||
>x : true
|
||||
}
|
||||
function foo6(x: number | string | boolean) {
|
||||
>foo6 : (x: string | number | boolean) => boolean
|
||||
@@ -167,7 +167,7 @@ function foo7(x: number | string | boolean) {
|
||||
>typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // x is number // do not change value : ((y = x) && x.toString()) : string
|
||||
>typeof x === "number" : boolean
|
||||
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>x : number | boolean
|
||||
>x : number | true
|
||||
>"number" : "number"
|
||||
|
||||
// change value of x
|
||||
@@ -187,13 +187,13 @@ function foo7(x: number | string | boolean) {
|
||||
: ((y = x) && x.toString()))); // x is boolean
|
||||
>((y = x) && x.toString()) : string
|
||||
>(y = x) && x.toString() : string
|
||||
>(y = x) : boolean
|
||||
>y = x : boolean
|
||||
>(y = x) : true
|
||||
>y = x : true
|
||||
>y : string | number | boolean
|
||||
>x : boolean
|
||||
>x : true
|
||||
>x.toString() : string
|
||||
>x.toString : () => string
|
||||
>x : boolean
|
||||
>x : true
|
||||
>toString : () => string
|
||||
}
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ function foo7(x: number | string | boolean) {
|
||||
>x : boolean
|
||||
>x.toString() : string
|
||||
>x.toString : () => string
|
||||
>x : boolean
|
||||
>x : true
|
||||
>toString : () => string
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
class DatasourceCommandWidgetElement {
|
||||
_commandBased: boolean;
|
||||
_commandElement: unknown;
|
||||
commandElement: unknown;
|
||||
|
||||
constructor(target: unknown) {
|
||||
if (target instanceof DatasourceCommandWidgetElement) {
|
||||
this._commandBased = true;
|
||||
this._commandElement = target.commandElement;
|
||||
} else {
|
||||
this._commandBased = false;
|
||||
}
|
||||
|
||||
if (this._commandBased = (target instanceof DatasourceCommandWidgetElement)) {
|
||||
this._commandElement = target.commandElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user