eqeqeq
It’s considered good practice to use type-safe equality operators === and !== instead of == and !=.
Rule Type: Suggestion
Fixable: Yes (in some cases)
Why This Rule Exists
The == and != operators do type coercion following obscure rules, leading to unexpected results:
[] == false // true
[] == ![] // true
3 == "03" // true
Using === and !== avoids these surprises by not performing type coercion.
Rule Details
This rule enforces use of type-safe equality operators.
Examples
Incorrect Code
if (x == 42) { }
if ("" == text) { }
if (obj.getStuff() != undefined) { }
Correct Code
if (x === 42) { }
if ("" === text) { }
if (obj.getStuff() !== undefined) { }
Options
"always" (default)
Enforce === and !== in every situation.
Incorrect:
a == b
foo == true
bananas != 1
value == undefined
typeof foo == 'undefined'
foo == null
Correct:
a === b
foo === true
bananas !== 1
value === undefined
typeof foo === 'undefined'
foo === null
null option
Customize how the rule treats null comparisons:
"always" (default) - Always use === or !==
"never" - Never use === or !== with null
"ignore" - Don’t check null comparisons
// With { "null": "ignore" }
foo == null // OK
foo === null // Also OK
"smart"
Allows == and != in these cases:
- Comparing two literal values
- Evaluating
typeof
- Comparing against
null
Incorrect:
// comparing two variables requires ===
a == b
// only one side is a literal
foo == true
bananas != 1
// comparing to undefined requires ===
value == undefined
Correct:
typeof foo == 'undefined'
'hello' != 'world'
0 == 0
true == true
foo == null
Common Patterns
null/undefined Checks
The one useful case for == is checking for null OR undefined.
// Using ==
if (value == null) {
// true if value is null OR undefined
}
// Equivalent with ===
if (value === null || value === undefined) {
// Same but more verbose
}
// Modern approach
if (value ?? false) {
// Use nullish coalescing
}
Type Coercion Surprises
These comparisons with == are all true, but probably not what you want!
// Array coercion
[] == false // true
[] == ![] // true
[] == '' // true
// String coercion
'' == 0 // true
'0' == 0 // true
'\n' == 0 // true
// Number coercion
3 == '03' // true
true == 1 // true
false == 0 // true
// null/undefined
null == undefined // true
Safe Type Coercion
// Wrong: Relying on coercion
if (arr.length == 0) { }
// Right: Explicit comparison
if (arr.length === 0) { }
// Wrong: String coercion
if (value == '0') { }
// Right: Explicit types
if (String(value) === '0') { }
if (value === 0 || value === '0') { }
Configuration Examples
// Always use ===
{
"rules": {
"eqeqeq": "error"
}
}
// Ignore null comparisons
{
"rules": {
"eqeqeq": ["error", "always", {
"null": "ignore"
}]
}
}
// Smart mode
{
"rules": {
"eqeqeq": ["error", "smart"]
}
}
Auto-fixing
This rule can auto-fix when:
- One operand is a
typeof expression
- Both operands are literals with the same type
eslint --fix your-file.js
When Not to Use It
Disable if you don’t want to enforce a style for equality operators. However, this is generally not recommended - the type-safe operators prevent many bugs.
Migration Tips
Finding Issues
# Find all == and != in your codebase
eslint . --rule 'eqeqeq: error'
Common Fixes
// Before
if (user.age == 18) { }
if (value != null) { }
if (typeof x == 'number') { }
// After
if (user.age === 18) { }
if (value !== null && value !== undefined) { }
if (typeof x === 'number') { }