oxc-project/oxc · error · OxcDiagnostic
Avoid using `.length` as the index in `Array#with()`.
Error message
Avoid using `.length` as the index in `Array#with()`.
What it means
Diagnostic from the oxlint rule `unicorn/no-confusing-array-with` (length-index arm, category: suspicious). Valid `.with()` indexes are `0..length-1`; `.with()` replaces an element and cannot append, so passing `arr.length` (one past the last valid index) always throws a RangeError at runtime. The rule catches this statically whenever the index is a `.length` member access on an expression provably identical to the call receiver, converting a guaranteed crash into a lint-time error.
Source
Thrown at crates/oxc_linter/src/rules/unicorn/no_confusing_array_with.rs:21
ast::{Expression, UnaryOperator},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use crate::{
AstNode, ast_util::is_method_call, context::LintContext, rule::Rule, utils::is_same_expression,
};
fn negative_index_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Avoid using a negative index with `Array#with()`.")
.with_note("`Array#with()` interprets a negative index as an offset from the end.")
.with_help("Use a non-negative index to make the intended position explicit.")
.with_label(span)
}
fn length_index_diagnostic(span: Span) -> OxcDiagnostic {
OxcDiagnostic::warn("Avoid using `.length` as the index in `Array#with()`.")
.with_note("An array's `.length` is one past its last valid index.")
.with_help("Use `.length - 1` to replace the last element.")
.with_label(span)
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ConfusingWithIndex {
Negative,
Length,
}
#[derive(Debug, Default, Clone)]
pub struct NoConfusingArrayWith;
declare_oxc_lint!(
/// ### What it does
///
/// Disallows confusing uses of [`Array#with()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/with).View on GitHub (pinned to e1e7af627c)
Solutions
- To append immutably, use spread: `const next = [...items, item]`
- To replace the last element, use `items.with(items.length - 1, item)`
- If the index is computed at runtime, validate it first: `if (!Number.isInteger(i) || i < 0 || i >= arr.length) throw new RangeError(...)`
Example fix
// before (always throws RangeError) const next = items.with(items.length, 'new'); // after const next = [...items, 'new'];
Defensive patterns
Strategy: validation
Validate before calling
function safeWith(arr, index, value) {
if (!Number.isInteger(index) || index < 0 || index >= arr.length) {
throw new RangeError(`index ${index} out of range 0..${arr.length - 1}`);
}
return arr.with(index, value);
} Try / catch
try {
arr.with(idx, value);
} catch (err) {
if (err instanceof RangeError) {
// report invalid index instead of crashing
}
throw err;
} Prevention
- Remember `.with()` is replace-only (0..length-1); use spread to append
- Bound-check computed indexes before calling `.with()`
- Keep this rule at error level in CI — it reports guaranteed crashes
When it happens
Trigger: `array.with(array.length, value)` (with any number of extra arguments), `object.items.with(object.items.length, value)` — the index is a static `.length` property whose object is the same expression as the receiver. `otherArray.length` or `array.length - 1` passes.
Common situations: Assuming `.with()` can grow the array, mirroring the `arr[arr.length] = v` mutation idiom; immutable-state code (React/Redux) rewriting elements; first contact with ES2023 change-by-copy methods.
Related errors
- Avoid using a negative index with `Array#with()`.
- Expected to call `super()`.
- The update clause in this loop moves the variable in the wro
- Avoid calls to the `Array` constructor
- Unexpected re-assignment of `const` variable {name}.
AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20).
Data as JSON: /api/errors/18308340568472a6.
Report an issue: GitHub.