oxc-project/oxc · error · OxcDiagnostic
Unexpected object literal comparison.
Error message
Unexpected object literal comparison.
What it means
Oxlint rule `oxc/bad-object-literal-comparison` fires on an equality comparison (`==`, `===`, `!=`, `!==`) in which one operand is an empty object literal `{}`. Every literal creates a fresh reference, so `x === {}` is always false and `x !== {}` always true; the help text reports that constant result and suggests `Object.entries()`/`Object.keys()` with a length check. The rule only matches empty object literals (the source checks `properties.is_empty()`).
Source
Thrown at crates/oxc_linter/src/rules/oxc/bad_object_literal_comparison.rs:10
use oxc_ast::{AstKind, ast::Expression};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use oxc_syntax::operator::BinaryOperator;
use crate::{AstNode, context::LintContext, rule::Rule};
fn object_comparison(span: Span, const_result: bool) -> OxcDiagnostic {
OxcDiagnostic::warn("Unexpected object literal comparison.")
.with_help(format!(
"This comparison will always return {const_result:?} as object literals are never equal to each other. Consider using `Object.entries()` of `Object.keys()` and comparing their lengths."
))
.with_label(span)
}
fn array_comparison(span: Span, const_result: bool) -> OxcDiagnostic {
OxcDiagnostic::warn("Unexpected array literal comparison.")
.with_help(format!("This comparison will always return {const_result:?} as array literals are never equal to each other. Consider using `Array.length` if empty checking was intended."))
.with_label(span)
}
#[derive(Debug, Default, Clone)]
pub struct BadObjectLiteralComparison;
declare_oxc_lint!(
/// ### What it does
///View on GitHub (pinned to e1e7af627c)
Solutions
- Replace with an emptiness check: `typeof x === 'object' && x !== null && Object.keys(x).length === 0`
- If deep content comparison was intended, use `assert.deepStrictEqual`, `lodash.isEqual`, or a custom deep-equal helper
- If identity comparison was intended, compare stable identifiers (e.g. `x.id === y.id`) instead of literals
Example fix
// before
if (x === {}) { /* never runs */ }
// after
if (x !== null && typeof x === 'object' && Object.keys(x).length === 0) { /* runs when empty */ } Defensive patterns
Strategy: type-guard
Validate before calling
// .oxlintrc.json — catch it before runtime
{
"rules": { "oxc/bad-object-literal-comparison": "error" }
} Type guard
function isEmptyObject(v) {
return typeof v === 'object' && v !== null && !Array.isArray(v) && Object.keys(v).length === 0;
}
if (isEmptyObject(x)) { /* ... */ } Prevention
- Treat any `{}` operand inside ==/===/!=/!== as an immediate smell
- Use Object.keys(...).length === 0 for emptiness and a deep-equal helper for content
- Enable the rule in CI so the always-false branch cannot ship
When it happens
Trigger: `if (x === {}) {}` (always false); `if (user !== {}) {}` (always true); `if (typeof person != 'object' || person != {}) {}`; any `==`/`===`/`!=`/`!==` comparison with a bare `{}` operand.
Common situations: Developers from Python/C# expecting value equality; attempting to test 'is the object empty'; hastily written default-options guards; comparisons auto-generated from schemas.
Related errors
- Unexpected array literal comparison.
- Left-hand side of `&&` operator has no effect.
- Right-hand side of `&&` operator has no effect.
- Unexpected constant comparison
- Both sides of the logical operator are equivalent
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/6ba82a6a2d610ec1.
Report an issue: GitHub.