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);