Array.prototype.toSpliced()
toSpliced(start, deleteCount, ...items) The toSpliced() method returns a new array with elements removed or replaced at a given index. Unlike splice() which mutates the original array, toSpliced() leaves your original data intact — essential for React state, Redux, and other immutability-required workflows.
Syntax
arr.toSpliced(start)
arr.toSpliced(start, deleteCount)
arr.toSpliced(start, deleteCount, ...items)
Parameters
| Parameter | Type | Description |
|---|---|---|
start | number | Index at which to start changing the array |
deleteCount | number | Optional number of elements to remove |
...items | any | Optional elements to add to the array |
Return Value
A new array with the specified changes applied. The original array is not modified.
Examples
Removing elements
const arr = ["a", "b", "c", "d", "e"];
const removed = arr.toSpliced(1, 2);
console.log(arr); // ["a", "b", "c", "d", "e"] — original unchanged
console.log(removed); // ["a", "d", "e"]
Removing is only one part of what toSpliced() can do. By supplying replacement items as additional arguments, you can swap out elements in one pass—removing the old and inserting the new at the same position. The same method signature supports three distinct operations: remove, replace, and insert, depending on the arguments.
Replacing elements
const fruits = ["apple", "banana", "cherry", "date"];
const swapped = fruits.toSpliced(1, 2, "orange", "grape");
console.log(fruits); // ["apple", "banana", "cherry", "date"] — original unchanged
console.log(swapped); // ["apple", "orange", "grape", "date"]
Set deleteCount to 0 and toSpliced() becomes a pure insert operation, sliding existing elements to the right. This is the immutable equivalent of calling splice(index, 0, ...items) to inject elements without removing anything. It is especially useful for adding items at the front or middle of a list.
Inserting without removing
const colors = ["red", "blue"];
const inserted = colors.toSpliced(1, 0, "green", "yellow");
console.log(colors); // ["red", "blue"] — original unchanged
console.log(inserted); // ["red", "green", "yellow", "blue"]
Numbers and strings are straightforward, but toSpliced() works with objects and arrays just as well. The new array shares references to the same objects, so modifying an object’s properties through one array remains visible through the other. Keep this in mind when altering nested structures.
Working with objects
const todos = [
{ id: 1, text: "Buy milk" },
{ id: 2, text: "Walk dog" },
{ id: 3, text: "Write code" }
];
const updated = todos.toSpliced(1, 1, { id: 2, text: "Feed cat" });
console.log(todos.length); // 3 (unchanged)
console.log(updated.length); // 3
console.log(updated[1].text); // "Feed cat"
Like splice(), toSpliced() accepts negative start values that count backward from the end. Passing -2 tells the method to start two positions before the last element, making it easy to replace items near the tail without computing the absolute index.
Negative indices
const letters = ["a", "b", "c", "d"];
const fromEnd = letters.toSpliced(-2, 1, "x");
console.log(letters); // ["a", "b", "c", "d"] — original unchanged
console.log(fromEnd); // ["a", "b", "x", "d"]
Each example so far works on plain arrays. The practical payoff becomes clearest when you apply toSpliced() to state management—React, Redux, and similar frameworks rely on immutability to detect changes, and toSpliced() produces a fresh array without extra cloning.
Practical: replacing item in React-style state
// Simulating React state update
let items = ["foo", "bar", "baz"];
// Old way with mutation (bad in React/Redux):
// items.splice(1, 1, "qux");
// New way with immutability:
items = items.toSpliced(1, 1, "qux");
console.log(items); // ["foo", "qux", "baz"]
When to Use toSpliced()
Choose toSpliced() over splice() when:
- Working with React state or Redux
- You need to preserve the original array for comparison
- Chaining with other array methods
- Functional programming patterns
How toSpliced() works
toSpliced() creates a new array of the appropriate length and copies elements from the original, skipping the deleted range and inserting the new items at the specified position. The original array is never touched. start follows the same negative-index convention as splice(): negative values count from the end of the array, and values outside the array bounds are clamped to 0 or array.length.
Return value compared to splice()
splice() returns the removed elements. toSpliced() returns the resulting array (with the changes applied). This is an intentional API difference: the return value of toSpliced() is what you work with next, while the return value of splice() is the discarded elements. Keep this in mind when migrating code.
const arr = ['a', 'b', 'c'];
// splice returns removed elements
const removed = arr.splice(1, 1); // removed = ['b'], arr = ['a', 'c']
// toSpliced returns the result
const result = ['a', 'b', 'c'].toSpliced(1, 1); // result = ['a', 'c']
Browser and runtime support
toSpliced() is part of the ES2023 “change array by copy” proposal and is available in Chrome 110+, Firefox 115+, Safari 16+, and Node.js 20+. For older environments, a polyfill is straightforward: [...arr.slice(0, start), ...items, ...arr.slice(start + deleteCount)] produces the same result without mutation.
Why toSpliced() Exists
toSpliced() exists to give you the same editing power as splice() without mutating the source array. That makes it a good fit for state containers, memoized data, and any code where preserving the original value makes debugging easier. It also reduces the temptation to clone an array by hand before editing it, because the method already expresses the full “copy, edit, return” workflow in one step.
See Also
Array.prototype.toSorted()— Return a sorted copy of an arrayArray.prototype.toReversed()— Return a reversed copy of an arrayArray.prototype.with()— Return copy with element at index replaced