Open greg-hornby-roam opened 2 years ago
Note that if getSomeData
returns a falsy value(false
, 0
, ""
...), the else branch will be executed, even the input is an instance of A or B.
What whzx5byb said. I don't see a bug here either.
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
}
@greg-hornby-roam It seems similar to https://github.com/microsoft/TypeScript/issues/33878
Hm, there are two separate things happening. One is that non-literals after the &&
eliminates the narrowing in the false branch, independent of aliasing the condition:
const someData = true;
if ((test instanceof A || test instanceof B) && someData) {
test; // A | B
} else {
test; // A | B | C
}
And the second is that aliasing does behave differently when the truthy &&
is inlined:
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
}
Pretty weird.
Bug Report
🔎 Search Terms
Control Flow Analysis of Aliased Conditions and Discriminants
🕗 Version & Regression Information
4.4+
⏯ Playground Link
Playground link with relevant code
💻 Code
🙁 Actual behavior
the else statement loses it's narrowing because getData is not strictly a boolean it seems.
🙂 Expected behavior
the if/else of getData should behave the same as the if/else of isAOrB