← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Type Coercion Gotchas (== vs ===)

JavaScript ES5 Intermediate
debt(d3/e1/b3/t7)
d3 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'default linter catches the common case' (d3). The detection_hints list ESLint and TypeScript as tools, and the code_pattern '== [^=]' is exactly what the ESLint `eqeqeq` rule flags by default. This is a well-known, commonly enabled lint rule that catches the primary misuse pattern automatically without any specialist configuration.

e1 Effort Remediation debt — work required to fix once spotted

Closest to 'one-line patch or single-call swap' (e1). The quick_fix is a direct mechanical replacement: swap == for === everywhere and enable the ESLint eqeqeq rule. Where coercion was intentional, an explicit Number()/String()/Boolean() conversion is a single-call swap. No cross-file refactor is required per instance.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). The choice to use == vs === is pervasive in JavaScript but the burden is moderate — it applies broadly across web and CLI contexts, but once the ESLint rule is enforced and the codebase is corrected, ongoing burden is low. It doesn't reshape architecture, but codebases with many loose comparisons impose a persistent review tax until corrected.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap — contradicts how a similar concept works elsewhere' (t7). The misconception field states developers believe '=== is overly strict and coercion is a feature.' The behavior of == directly contradicts intuitions from most other languages (where equality checks types), and the coercion table (0 == '0' == false, null == undefined but null !== false) is notoriously non-intuitive. The security implications (auth bypasses) make the wrong assumption costly, pushing this above t5.

About DEBT scoring →

TL;DR

JavaScript's == performs type coercion producing surprising results — '0' == false (true), [] == false (true), null == undefined (true) — use === always.

Explanation

JavaScript's Abstract Equality Comparison (==) coerces types before comparing. Famous gotchas: '' == false (true), '0' == false (true), [] == false (true), [] == ![] (true), null == undefined (true), null == false (false — null only == undefined). The + operator also coerces: 1 + '2' = '12', [] + {} = '[object Object]', {} + [] = 0. Practical rule: always use ===, use explicit Number()/String() conversions, enable ESLint eqeqeq rule. TypeScript strict mode eliminates most coercion bugs.

Common Misconception

Using === everywhere is overly strict — it prevents real bugs. Coercion is a feature, not a bug.

Why It Matters

Type coercion in security checks (passwords, IDs) is critical — 0 == '0' == false enables auth bypasses comparable to PHP's type juggling vulnerabilities.

Common Mistakes

  • Using == for comparisons — enables accidental type coercion.
  • String/number comparison in conditions: if (userId == '123').
  • Forgetting that + coerces to string when one operand is a string.

Code Examples

✗ Vulnerable
0 == '0'        // true
0 == false      // true
'' == false     // true
null == false   // false (surprise)
1 + '2'         // '12' (string!)
✓ Fixed
// Always use === :
0 === '0'       // false
0 === false     // false

// Explicit conversions:
const total = Number(priceStr) + Number(taxStr);

// ESLint rule:
// "eqeqeq": "error"

Added 22 Mar 2026
Edited 5 Apr 2026
Views 73
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping F 1 ping S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 2 pings M 0 pings T 1 ping W 1 ping T 1 ping F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Amazonbot 10 Google 6 Scrapy 6 PetalBot 6 Ahrefs 5 Perplexity 4 Unknown AI 3 Brave Search 2 Applebot 2 SEMrush 2 Majestic 1 Meta AI 1 Twitter/X 1 Bing 1
crawler 47 crawler_json 2 pre-tracking 1
🧱 FUNDAMENTALS — new to this? Start with the ground floor.
JavaScript javascript The programming language of the browser — it reads and modifies the page (the DOM), reacts to user events, and fetches data without reloading.

JavaScript is the only language browsers execute, so every interactive behaviour on the web goes through it. Its two defining traits — single-threaded event loop and loose typing (== coercion) — explain the majority of both its bugs and its design patterns.

💡 Default to const, use === always, and reach for let only when a value genuinely reassigns.

Ask Codex about JavaScript →
Truthy and Falsy javascript In JavaScript, every value is either "truthy" (treated as true in a boolean context) or "falsy" (treated as false). This determines how values behave in if statements and logical operations.

Nearly every conditional and logical operator in JavaScript relies on truthy/falsy conversion. Mastering the six falsy values lets you write cleaner checks and avoid subtle bugs that trip up even experienced developers.

💡 Memorize the six falsy values: false, 0, "", null, undefined, NaN—everything else is truthy.

Ask Codex about Truthy and Falsy →
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Low
⚡ Quick Fix
Use === everywhere. Enable ESLint eqeqeq rule. Use explicit Number()/String()/Boolean() conversions. Use TypeScript strict mode to catch coercion bugs at compile time.
📦 Applies To
javascript ES5 web cli
🔗 Prerequisites
🔍 Detection Hints
== [^=]
Auto-detectable: ✓ Yes eslint typescript
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: Line
CWE-697 CWE-704


✓ schema.org compliant