{"record":{"id":"2bd334d39103d8a4","repo":"oxc-project/oxc","slug":"avoid-using-a-negative-index-with-array-with","errorCode":null,"errorMessage":"Avoid using a negative index with `Array#with()`.","messagePattern":"Avoid using a negative index with `Array#with\\(\\)`\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/unicorn/no_confusing_array_with.rs","lineNumber":14,"sourceCode":"use oxc_ast::{\n    AstKind,\n    ast::{Expression, UnaryOperator},\n};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_span::Span;\n\nuse crate::{\n    AstNode, ast_util::is_method_call, context::LintContext, rule::Rule, utils::is_same_expression,\n};\n\nfn negative_index_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Avoid using a negative index with `Array#with()`.\")\n        .with_note(\"`Array#with()` interprets a negative index as an offset from the end.\")\n        .with_help(\"Use a non-negative index to make the intended position explicit.\")\n        .with_label(span)\n}\n\nfn length_index_diagnostic(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Avoid using `.length` as the index in `Array#with()`.\")\n        .with_note(\"An array's `.length` is one past its last valid index.\")\n        .with_help(\"Use `.length - 1` to replace the last element.\")\n        .with_label(span)\n}\n\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]\nenum ConfusingWithIndex {\n    Negative,\n    Length,\n}\n","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/unicorn/no_confusing_array_with.rs#L1-L32","documentation":"Diagnostic from the oxlint rule `unicorn/no-confusing-array-with` (negative-index arm, category: suspicious). `Array.prototype.with(index, value)` interprets a negative index as an offset from the end of the array — unlike `slice()`/`splice()` intuition — so `array.with(-1, v)` replaces the last element. Because that surprises most readers, the rule flags statically negative indexes and asks for a non-negative position instead.","triggerScenarios":"Any `x.with(idx, ...)` call whose first argument statically evaluates to a negative number: `array.with(-1, value)`, `array.with(-2, value)`, `array.with(-1.5, value)`, `array.with(-(-(-1)))`. Dynamic indexes (`array.with(i)`), `-0`, `+1`, and `-1e400` (not finite-negative by truncation rules) pass.","commonSituations":"Porting `.at(-1)` or negative-splice idioms to the newer ES2023 `.with()`; adopting change-by-copy methods in codebases that had polyfills with different semantics; code review disputes about negative indexes.","solutions":["Rewrite with an explicit non-negative index: `array.with(array.length - 1, value)` targets the last element","Store the position in a variable (`const last = items.length - 1;`) when the same offset is reused","If the end-relative offset is intentional and agreed, suppress once with `// oxlint-disable-next-line unicorn/no-confusing-array-with`"],"exampleFix":"// before\nconst updated = items.with(-1, 'last');\n\n// after\nconst updated = items.with(items.length - 1, 'last');","handlingStrategy":"validation","validationCode":"// explicit, lint-clean helper for end-relative replacement\nfunction withFromEnd(arr, offsetFromEnd, value) {\n  const index = arr.length - 1 - offsetFromEnd;\n  if (index < 0) throw new RangeError('offset past start');\n  return arr.with(index, value);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer non-negative indexes in `.with()`; reserve negative indexes for `.at()`","Unit-test boundary positions (0, length-1, length) whenever `.with()` is introduced","Enable unicorn/no-confusing-array-with in CI rather than relying on review"],"tags":["arrays","es2023","suspicious-code","oxlint"],"backgroundTag":"negative-index-confusion","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"}