Small bugs can creep in from unexpected places. Bad values can make your conditional logic fail in unexpected ways. Let's take a quick look at the headaches of bad inequality.
Basics
These functions are not the same. They are mostly the same but they have a very specific difference. Do you see it?
const one = (a) => a > 10;
const two = (a) => !(a <= 10);
Whenever we perform inequality checks with undefined
or NaN
, the result is false
. If we don't explicitly check for edge cases, two "equivalent" checks can return different answers.
one(NaN)
returns false
, but two(NaN)
returns true
!
How it Happens
if (!(value <= 10)) {
// ...
If you come across that code, you might change it to if (a > 10) {
without hesitation.
- It's shorter.
- It is easier to read.
- For all normal values they are the same.
Why it Matters
But we don't always get normal values. This could be a breaking change to your code. It could cause very difficult to troubleshoot defects. Nothing in this simple code suggests that we might encounter "bad" values, so you might miss it entirely.
Type safety won't fix this, either, because NaN
is a number...it's just a bad one.
Conclusion
If you encounter a strange condition like this in your code, ask yourself what happens to the wrong value if you change it. Hopefully your code prevents you from getting a bad value and performing a "bad comparison", but being a little defensive about these changes can save a lot of trouble for your future self.
In cases like these it is usually better to have explicit checks for bad values. These communicate possible inputs and expected results clearly to other developers.
if (Number.isNaN(value) || value > 10) {
// ...
Top comments (1)
Straight to the point and crystal! Thanks :)