{"record":{"id":"301805c57156dc76","repo":"oxc-project/oxc","slug":"unexpected-comparison-to-newly-constructed-object","errorCode":null,"errorMessage":"Unexpected comparison to newly constructed object","messagePattern":"Unexpected comparison to newly constructed object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/oxc_linter/src/rules/eslint/no_constant_binary_expression.rs","lineNumber":98,"sourceCode":"\nfn constant_short_circuit(lhs_name: &str, expr_name: &str, span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(format!(\n        \"Unexpected constant {lhs_name} on the left-hand side of a {expr_name:?} expression\"\n    ))\n    .with_help(\"This expression always evaluates to the constant on the left-hand side\")\n    .with_label(span)\n}\n\nfn constant_binary_operand(left_or_right: &str, operator: &str, span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected constant binary expression\")\n        .with_help(format!(\n            \"This compares constantly with the {left_or_right}-hand side of the {operator}\"\n        ))\n        .with_label(span)\n}\n\nfn constant_always_new(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected comparison to newly constructed object\")\n        .with_help(\"These two values can never be equal\")\n        .with_label(span)\n}\n\nfn constant_both_always_new(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected comparison of two newly constructed objects\")\n        .with_help(\"These two values can never be equal\")\n        .with_label(span)\n}\n\nfn constant_relational_comparison(operator: &str, span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Unexpected constant relational comparison\")\n        .with_help(format!(\"Both sides of the {operator} are literal values\"))\n        .with_label(span)\n}\n\nimpl Rule for NoConstantBinaryExpression {\n    fn from_configuration(value: serde_json::Value) -> Result<Self, serde_json::error::Error> {","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/no_constant_binary_expression.rs#L80-L116","documentation":"Diagnostic from `no-constant-binary-expression`, emitted by `constant_always_new` (crates/oxc_linter/src/rules/eslint/no_constant_binary_expression.rs:97). It fires on strict equality/inequality (`===`/`!==`) where either operand is an expression that always yields a fresh reference — object literal, array literal, function/arrow/class expression, regex literal, or `new` of a builtin global (Promise, WeakSet, Boolean...). JS compares objects by reference, so `x === {}` (or `x === new Foo()` for known globals) can never be true; the result is a constant false.","triggerScenarios":"BinaryExpression with StrictEquality/StrictInequality where `is_always_new(left)` or `is_always_new(right)` — e.g. `x === []`, `x !== () => {}`, `isEmpty = x === []`, `x === new Promise(...)` when the callee is an ECMAScript global.","commonSituations":"Developers from value-comparison languages (Python, Java equals) writing `x === []` or `obj === {}` emptiness checks; comparing freshly constructed objects for identity; the classic `x.length === 0` vs `x === []` confusion documented in the rule's doc comment.","solutions":["Test the property you actually care about: `x.length === 0`, `Object.keys(x).length === 0`, or `Number.isNaN(x)`.","For identity checks, compare against a stored reference (a previously created object), not a freshly constructed one.","For deep equality use a comparison helper (`isEqual` from lodash, `assert.deepStrictEqual`).","If the always-false comparison is a deliberate sentinel, replace it with the literal `false` so readers are not misled."],"exampleFix":"// before\nconst isEmpty = x === [];\n\n// after\nconst isEmpty = Array.isArray(x) && x.length === 0;","handlingStrategy":"type-guard","validationCode":"// Gate: strict-equality against freshly constructed references\nconst freshRefCompare = /={2,3}\\s*(\\[|\\{|=>|function|class\\b|\\/|new\\s+(Promise|WeakSet|Boolean|Map|Set)\\b)/.test(src);","typeGuard":"// Name the check you actually mean\nconst isEmptyArray = (v) => Array.isArray(v) && v.length === 0;\nconst isEmptyObject = (v) => v !== null && typeof v === 'object' && Object.keys(v).length === 0;\nconst isSameRef = (a, b) => a === b; // only meaningful for shared references","tryCatchPattern":null,"preventionTips":["Never compare against a literal object/array/function on either side of ===.","Store references you intend to compare, then compare the stored bindings.","Use deep-equal helpers for content comparison."],"tags":["lint","reference-equality","object-comparison","dead-code","oxlint"],"backgroundTag":"reference-equality-new-object","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}