Skip to main content
Beta: Front-End Checklist is currently in beta. Some issues are still being fixed. Thanks for your patience.

Avoid implicit type coercion

Use strict equality (===), explicit type conversion, and Number/String/Boolean constructors to avoid JavaScript's implicit type coercion producing unexpected results.

Utilities
Quick take
Typical fix time 15 min
  • Always use === and !== instead of == and !=
  • Convert types explicitly with Number(), String(), Boolean(), parseInt()
  • Be careful with + operator — it concatenates strings but adds numbers
  • Use Array.isArray() instead of typeof for array checks
Why it matters: JavaScript's implicit type coercion produces results that look like bugs to anyone who doesn't know the exact coercion rules. `==` comparisons with mixed types silently convert values in ways that fail to catch genuine errors. Explicit conversions make code intent clear and catch real type mismatches at the point where they occur.

Rule Details

JavaScript will silently convert types when you use operators that expect a specific type. The results are often surprising, especially with equality comparisons.

Code Example

// ❌ == performs type coercion before comparing
0 == false    // true (both coerce to 0)
'' == false   // true
null == undefined // true
'5' == 5      // true
[] == false   // true
[] == ![]     // true (this is famously confusing)
 
// ✅ === compares value AND type
0 === false   // false
'5' === 5     // false
null === undefined // false

Why It Matters

JavaScript's implicit type coercion produces results that look like bugs to anyone who doesn't know the exact coercion rules. == comparisons with mixed types silently convert values in ways that fail to catch genuine errors. Explicit conversions make code intent clear and catch real type mismatches at the point where they occur.

Explicit Type Conversion

// Converting to Number
const input = document.getElementById('price').value // '12.50' (string)
 
// ❌ Implicit — relies on coercion
const total = input * 100
 
// ✅ Explicit — intent is clear
const total = Number(input) * 100
const total = parseFloat(input) * 100
 
// parseInt for integers (always provide radix)
const pageNum = parseInt(params.get('page'), 10)

The + Operator Trap

// + prefers string concatenation when one operand is a string
'5' + 3      // '53' — string concatenation!
5 + '3'      // '53'
5 + 3        // 8 — numeric addition
 
// Force numeric addition
Number('5') + 3  // 8
+'5' + 3         // 8 (unary + converts to number)
parseInt('5', 10) + 3 // 8

Type Checking

// typeof has surprises
typeof null       // 'object' — historical bug
typeof []         // 'object' — not helpful
typeof function(){} // 'function'
 
// ✅ Specific checks
Array.isArray([])           // true
value === null              // true for null
value instanceof Date       // true for Date objects
Object.prototype.toString.call(value) === '[object RegExp]' // for RegExp

Falsy Values to Know

// These are all falsy in JavaScript:
false, 0, -0, 0n, '', null, undefined, NaN
 
// Common trap — 0 is falsy!
const count = 0
if (count) {
  // This block never runs for count = 0
}
 
// ✅ Be explicit for numeric checks
if (count !== 0) { /* runs for count = 0 */ }
if (count > 0) { /* only positive */ }
 
// Another trap — empty array and object are truthy!
if ([])  { /* runs! */ }
if ({})  { /* runs! */ }

ESLint Rules

{
  "rules": {
    "eqeqeq": ["error", "always"],
    "no-implicit-coercion": "warn"
  }
}

Exceptions

  • A framework default or browser behavior is not an exception by itself; only documented constraints with compensating controls should suppress the finding.
  • When a JavaScript pattern looks unsafe but the data is fully constrained, validated, and never attacker-controlled, document that boundary explicitly instead of treating it as implicit.
  • If a rule overlaps with a stronger exploit path or runtime failure, fix the issue that most directly enables compromise or user-visible breakage first.

Verification

Automated Checks

  • Verify the behavior in the browser after the code change, not only in static analysis.
  • Inspect DevTools Network or Performance panels when the rule affects loading or execution order.
  • Test the primary user flow and one edge case triggered by the changed script path.

Manual Checks

  • Confirm the code still behaves correctly when the feature is delayed, lazy-loaded, or fails.

Use with AI

Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.

Check

Verify implementation

Find all uses of == and != (non-strict equality) in this file. Also look for implicit type conversions from + operator and other coercion traps.

Fix

Auto-fix issues

Replace all == with === and != with !==. Add explicit type conversions where mixed types are intentionally compared.

Explain

Learn more

Explain JavaScript's implicit type coercion rules, why == is problematic, and how to write safe type comparisons.

Review

Code review

Review scripts, client components, and browser execution paths related to Avoid implicit type coercion. Flag exact imports, event handlers, runtime side effects, or blocking operations that violate the rule, and state how the change should be verified in the browser.

Sources

References used to support the guidance in this rule.

Further Reading

Tools and supplementary material for exploring the topic in more depth.

ESLint (eqeqeq rule)eslint.orgTool

Rules that often go hand-in-hand with this one.

Lint JavaScript code

JavaScript code is linted with ESLint to detect errors and enforce coding standards.

JavaScript
Enable TypeScript strict mode in tsconfig.json

Enable "strict": true in tsconfig.json to activate the full suite of TypeScript type-checking flags and catch the most common runtime bugs at compile time.

JavaScript
Parse JSON safely with error handling

Always wrap JSON.parse() in try/catch and validate the parsed structure before use, as invalid JSON or unexpected data shapes cause runtime errors.

JavaScript
Avoid the any type — use unknown, generics, or type guards instead

Replace TypeScript's any type with unknown, proper generics, or narrowed type assertions to preserve type safety without sacrificing expressiveness.

JavaScript

Was this rule helpful?

Your feedback helps improve rule quality. This stays internal for now.

Loading feedback...
0 / 385