Equality Between Unrelated-Type Literals
ID |
javascript.equals_unrelated_types |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
CWE:597, reliability, suspicious-comparison |
Description
Reports equality and inequality comparisons (==, !=, ===, !==) where both sides are literals of unrelated types — for example 1 == "1", true === 0, [] == "". The result is statically decidable and is, in every realistic case, a typo or a refactor leftover.
The rule fires only when both operands are literals; one literal vs. an identifier is out of scope because the identifier’s runtime type cannot be inferred without flow analysis. The null == undefined idiom (the canonical "is null-ish" check, e.g. x == null) is also kept allowed.
Rationale
// Bad — every comparison is a constant.
if (1 == "1") doStuff(); // true (with type coercion)
if (1 === "1") doStuff(); // false (always)
if (true == 0) doStuff(); // false
if ([] == "") doStuff(); // true (loose-eq weirdness)
Loose equality applies type coercion, which makes the outcome surprising but constant. Strict equality between unrelated-type literals is just a constant false. Either way the comparison adds no information — the branch is effectively if (true) or if (false).
Remediation
Either fix the operand to the type the comparison expects, or — if the comparison is genuinely meant to test runtime type — use typeof:
// Good — compare like with like.
if (n === 1) doStuff();
if (s === "1") doStuff();
// Good — explicit type test.
if (typeof value === "number") handleNumber(value);