question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

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

See original GitHub issue

Bug Report

🔎 Search Terms

Control Flow Analysis of Aliased Conditions and Discriminants

🕗 Version & Regression Information

4.4+

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about control flow analysis

⏯ Playground Link

Playground link with relevant code

💻 Code

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
}

🙁 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

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
whzx5bybcommented, Sep 5, 2022

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.

2reactions
andrewbranchcommented, Sep 9, 2022

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Control flow analysis of aliased conditional expressions in ...
Control flow analysis of aliased conditional expressions in TypeScript ... foo is a boolean); a discriminant property of bar (i.e. bar is a ......
Read more >
Announcing TypeScript 4.4 RC - Microsoft Developer Blogs
Control Flow Analysis of Aliased Conditions and Discriminants. In JavaScript, we often have to probe a variable in different ways to see if...
Read more >
Get the best of TypeScript Control Flow Analysis - Retool
Control Flow Analysis is a core TypeScript feature that analyzes the code to get the best type inference depending on variable usages; ...
Read more >
Typescript Type Guard wont affect the variable type if set ...
... as Control Flow Analysis of Aliased Conditions and Discriminants in the ... In the given context , if isKind1 === true then...
Read more >
Control Flow in JavaScript: Conditional Statements - Medium
Logical operators are most commonly used to link multiple boolean comparison statements and return either true or false depending on the conditions. The...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found