TypeScript Control Flow Analysis of Aliased Conditions and Discriminants breaks on else statement if condition not strictly boolean

hmtdttj4  于 6个月前  发布在  TypeScript
关注(0)|答案(6)|浏览(48)

Bug报告

🔎 搜索词

别名条件和判别式的控制流分析

🕗 版本与回归信息

4.4+

  • 这个行为在每个我尝试过的版本中都是这样的,我也查阅了关于控制流分析的常见问题解答条目。

⏯ Playground链接

带有相关代码的Playground链接

💻 代码

class A {}
class B {}
class C {}

declare const test: A | B | C;

const isAOrB = (test instanceof A || test instanceof B);

declare function getSomeData(input: A | B): {}
const getData = (test instanceof A || test instanceof B) && getSomeData(test);

if (isAOrB) {
  test; //expect A | B - passes
} else {
  test; //expect C - passes
}

if (getData) {
  test; //expect A | B - passes
} else {
  test; //expect C - fails
}

🙁 实际行为

else语句失去了它的缩小作用,因为getData似乎不是一个严格意义上的布尔值。

🙂 预期行为

getData的if/else应该与isAOrB的if/else行为相同。

omvjsjqw

omvjsjqw1#

请注意,如果 getSomeData 返回一个假值(false0""...),即使输入是 A 或 B 的示例,else 分支也会被执行。

ipakzgxi

ipakzgxi2#

whzx5byb所说的话。我在这里也没有看到一个错误。

wlwcrazw

wlwcrazw3#

Okay my bad let me change the return type of getSomeData that it can't allow falsey values.
It's still the same issue

class A {}
class B {}
class C {}

declare const test: A | B | C;

const isAOrB = (test instanceof A || test instanceof B);

declare function getSomeData(input: A | B): {prop1: string; prop2: number;}
const getData = (test instanceof A || test instanceof B) && getSomeData(test);

if (isAOrB) {
  test; //expect A | B - passes
} else {
  test; //expect C - passes
}

if (getData) {
  test; //expect A | B - passes
} else {
  test; //expect C - fails
}

https://www.typescriptlang.org/play?ts=4.4.4#code/MYGwhgzhAECC0G8C+AoUkYCFGvVaAwjiigCYCm6ATudMAPYB2EALtC+awFxzQA+0bAIIBuEg2ZsAlhFgB5KtgC80ABQdW0KZLCNg5egDNefARuk69B45gCUYspXA1ohgK56WUptADm5FgBlegBbcgARMBYwVW0ABzcWHngBOx4EOKp6OIBGHlYqbV8RaEzsgCYeRjcQgCNyKhFcJk1-Fkjo6BV1TgtWXX0jEzNerUtBm1toADJpvwDgsI6Y83sSKWNY2QU7RBRodl6SgHpj8gAPOMo2FMFoAFpSjE4UJGhyEAhaBH3D1hOzpdroQHk8oC9UCgNmo2sspj8DuYARcrsAbvw7o84s8IK93p9vr8kdBTijgURHoYwFJPq8gA

92dk7w1h

92dk7w1h5#

嗯,这里有两个独立发生的事情。一个是 && 之后的非字面量消除了假分支中的缩小,而与条件别名无关:

const someData = true;
if ((test instanceof A || test instanceof B) && someData) {
  test; // A | B
} else {
  test; // A | B | C
}

第二个是当真值 && 被内联时,别名 确实表现得不同:

if ((test instanceof A || test instanceof B) && true) {
  test; // A | B
} else {
  test; // C
}

const aliasedCondition = (test instanceof A || test instanceof B) && true;
if (aliasedCondition) {
  test; // A | B
} else {
  test; // A | B | C
}

相当奇怪。

kdfy810k

kdfy810k6#

在普通情况下,只有true/false关键字有效。链接

if ((test instanceof A || test instanceof B) && 11) {
  test; //expect A | B - passes
} else {
  test; //expect C - fails
}

相关问题