The unfortunate reality when it comes to the TypeScript compiler is that it doesn't quite match up to human intelligence (at least not in TypeScript 3.4). This means that its control flow analysis falls short compared to what a human can do. While the compiler is consistent in its analysis, my own analytical skills tend to falter when I'm hungry.
If you perform a check on a variable with a union type and eliminate one or more of the options within that union, the compiler will appropriately narrow down the type of the variable:
param1.charAt(0); // error, possibly undefined
if (!param1) return;
param1.charAt(0); // now okay
However, one limitation of the compiler is that it does not track correlated variables outside of discriminated unions. By checking for
if (!param1 && !param2) return;
You are removing the possibility of both param1
and param2
being
undefined</code simultaneously, linking these formerly independent variables. The compiler does not recognize this correlation, treating them as independent entities, causing your issue to persist.</p>
<p>As suggested in another answer, you could utilize a <a href="https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions" rel="noreferrer">type assertion</a> if you believe you have a better understanding than the compiler:</p>
<pre><code>const param3 = param1 ? param1 : param2!.someProp; // Showing superiority over the compiler š¤
I've used the non-null assertion operator !
to assert dominance over the machine. Keep in mind that such assertions carry risks, so ensure there's no chance of param2
being
undefined</code before proceeding.</p>
<hr>
<p>An alternative approach is restructuring your code to guide the compiler through a feasible analysis:</p>
<pre><code>const param3 = param1 || (param2 ? param2.someProp : undefined);
if (!param3) return;
param3.charAt(0); // string
This method streamlines the process while ensuring each parameter is only checked once. The variable param3
is of type string | undefined
, only becoming
undefined</code if both <code>param1
and
param2
are falsy. It eliminates union constituents for each variable step by step without confusing the compiler with correlated types.
Either solution should address your needs. Best of luck! hope this proves helpful.