Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why does TypeScript think the variable can be undefined when it can't be?

I recently ran into a problem where TypeScript wrongly thinks a variable can be undefined. this is a simplified version:

const f = (a?: boolean, b?: boolean) => {
  if (!a && !b) return;
  let c: boolean;
  if (a) c = false;
  else c = b;
}

In the else c = b; line, a is false or undefined and b can only be true because otherwise !a && !b would have been true. but TypeScript throws an error saying:

Type 'boolean | undefined' is not assignable to type 'boolean'.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

TypeScript Playground

To fix the problem for now, i have added || !b to the if (a) c = false; line:

const f = (a?: boolean, b?: boolean) => {
  if (!a && !b) return;
  let c: boolean;
  if (a || !b) c = false;
  else c = b;
}

TypeScript Playground

But i’m curious as to why this error happens and TypeScript can’t detect that the variable cannot be undefined.

>Solution :

Half-joking answer: because typescript doesn’t model quantum entanglement.

More seriously, typescript’s type narrowing is basically a one-way process. It starts at the top and walks through all the branches of the code, narrowing as it goes. To detect the situation you’re asking about it would need to be able to back track, or to remember more complicated associations than the type system supports

Let’s step through the code and see what typescript sees. First we have this:

if (!a && !b) return;

Before this line, a is boolean | undefined, and so is b. Typescript tries to narrow these down, but it can’t. a might still be undefined (if b is true), and vice versa. So after this line, a‘s type is still boolean | undefined, and same for b.

A bit later we get to this:

if (a) c = false;

Looking only at the types and the code on this line, what can typescript deduce? It knows that if we get into the else case, then a must be false or undefined. But it can’t deduce anything about b.

To deduce something about b you need to know about the previous checks that have happened to b. Typescript does indirectly have information about the past checks: it has b‘s narrowed type. But since the type didn’t actually narrow (it’s still boolean | undefined), that won’t help here. Typescript would either need to have the ability to backtrack and re-evaluate, or to support types that encode the correlation between multiple variables (see quantum entanglement joke)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading