In JavaScript, null operands in a relational expression are treated as 0:
function f() { return /* either a number or null */; }
let b = f() < 0; // false if f() returns null
But in TypeScript, if I provide a type annotation for f
and turn on strict null checking, then I get the compiler error Object is possibly 'null'
:
function f(): number | null { return /* either a number or null */; }
let b = f() < 0; // <-- error TS2531
Is there a way to tell the compiler that nullable operands are acceptable here?
I can shut the compiler up with a non-null assertion on f()
, but I worry that f()!
could mislead code reviewers because f()
can return null here.
nonNumber < number
replies on javascript type coercion to work (converts null
to a number
when compared to a number). And type coercion is which is widely regarded as something to avoid in all javascript programs due to non obvious ways that values are transformed.
Typescript is assuming that more often than not, a nullable number used in a comparison is probably a potential bug. It's likely the programmer just forgot that the variable could be null
when writing that comparison.
So what typescript wants is for you to explicitly handle the null
case. This tells readers of your code exactly what happens if that value is null
and that the original programmer intended null
to be handled precisely that way.
Something like this perhaps?
const val = f()
let b = val !== null && val < 0
or:
let b = (f() ?? 0) < 0
You could use f()!
as you note, and that should work to silence the error. However, the !
is intended to say "the programmer is asserting that this value is not null
here, even if the compiler thinks it might be". Which isn't quite accurate, as you already noted.