A safer way to update a single array element
Updating one element in an array normally means mutating the original. The new Array.prototype.with(index, value) method changes that: it returns a copy of the array with the element at index replaced by value, leaving the original untouched.
For example, given an array of ages, you can produce an updated copy where the second item changes from 15 to 16:
const ages = [10, 15, 20, 25];
const newAges = ages.with(1, 16);
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)
The call ages.with(1, 16) reads as: take a copy of ages, replace the element at index 1, and return the new array. The original ages stays as [17, 15, 21].
The contrast with bracket notation is sharp. Assigning a mutated copy back to the same variable only creates a second reference to the same array:
const ages = [10, 15, 20, 25];
const newAges = ages;
newAges[1] = 16;
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 16, 20, 25] (Also changed 🙁)
Because JavaScript arrays are reference types, newAges and ages point to the same object. Any change through one reference is visible through the other. .with() avoids that hazard by giving you a true copy.
Why immutability matters
Immutable data is a core assumption in many frontend stacks. React and Redux rely on it for predictable state updates; Vue integrates it into its reactivity model. Angular and Lit don't require it, but encourage it because immutable updates make change detection faster and more reliable.
Before .with(), achieving a single-element immutable update meant reaching for spread syntax or .map(), which obscures the intent:
const ages = [10, 15, 20, 25];
const newAges = ages.map((age, index) => {
if (index === 1) {
return 16;
}
return age;
});
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (Remains unchanged)
Chaining and real-world use
Because .with() returns a fresh array, it composes naturally with other array methods. You can chain calls to update multiple positions in one expression:
const ages = [10, 15, 20, 25];
const newAges = ages.with(1, ages[1] + 1).with(2, ages[2] + 1)
console.log(newAges); // [10, 16, 21, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)
This works well in frameworks like React, where state updates expect new array references. Combined with a state setter, .with() gives a concise, readable way to immutably update a single entry in a list.
Three sibling methods
.with() is not the only new non-mutating array method. Three related helpers arrived alongside it:
Array.prototype.toReversed()— a copying version of.reverse().Array.prototype.toSorted()— a copying version of.sort().Array.prototype.toSpliced()— a copying version of.splice().
Together, these four methods cover the common array transformations without ever mutating the underlying data. For the specific case of replacing one element, .with() is the clearest and most direct option now available.



