Array.prototype.toSpliced()
Returns a copy of the array with elements removed at an index and optional new elements inserted.
toSpliced(start)
toSpliced(start, skipCount)
toSpliced(start, skipCount, item1)
toSpliced(start, skipCount, item1, item2, /* …, */ itemN)- Added in JavaScript ECMAScript 2023
Parameters
| Parameter | Type | Description |
|---|---|---|
$start | number | Zero-based index at which to start changing, converted to an integer. Negative values count back from the end; values past the end append instead of removing. |
$skipCountoptional | number= array.length - start | Number of elements to omit starting at start. Omitted, every element from start onward is removed; zero or negative removes nothing. |
$item1, …, itemNoptional | any | Elements to insert at start. If none are given, the method only removes. |
Return value
ArrayA new array made of the elements before start, then the given items, then the elements from start + skipCount onward.
Errors
Throws a TypeError if called on null or undefined, or a RangeError if the resulting length would exceed 2**32 - 1.
toSpliced() is the copying counterpart of splice(), and it inverts what the two return. splice() mutates the array and hands back the removed elements; toSpliced() leaves the array alone and hands back the resulting array. Getting those two confused is the usual first bug.
When to reach for it
It is the general-purpose immutable edit: insert at a position (skipCount of 0), delete a range (no items), or replace a slice with a different number of elements — the one thing with() cannot do. Reducers and state updates use it constantly.
What trips people up
- Omitting
skipCountis not the same as passing 0.arr.toSpliced(2)deletes everything from index 2 onward;arr.toSpliced(2, 0)deletes nothing. To append items at a position, you must pass the 0 explicitly. - Items are inserted, not spread. Passing an array inserts that array as a single element — use
...to splice several values in. - The result is always dense, so holes in a sparse source become
undefined. - The copy is shallow; untouched elements are the same references.
Example
When to use it
- Insert an item at a specific position in immutable list state.
- Remove one row by index and get the resulting array back in a single expression.
- Replace a slice of an array with a different number of elements.
- Append to an array without mutating it by splicing at the end with a skipCount of 0.
Frequently asked questions
How do I insert into an array without mutating it?
Call arr.toSpliced(index, 0, value) — the explicit 0 skipCount means nothing is removed, so the value is inserted at that position in the returned copy. Omitting the 0 would delete everything from index onward.
What is the difference between splice() and toSpliced()?
splice() mutates the array and returns the removed elements; toSpliced() leaves the array unchanged and returns the resulting array. The parameters are the same, but the return values mean opposite things.
How do I remove one element by index immutably?
Use arr.toSpliced(index, 1), which returns a new array without that element. For removing by value, filter() is usually clearer than finding the index first.
More examples
Immutable insert, remove and move
Each call produces a fresh array, so chaining them performs a move without ever touching list. The final log confirms the source is still in its original order.
const list = ["a", "b", "c", "d"];
const removed = list.toSpliced(1, 1);
console.log(removed);
// Move "d" to the front: remove it, then insert it
console.log(list.toSpliced(3, 1).toSpliced(0, 0, list[3]));
console.log(list);toSpliced() vs splice() return values
toSpliced() prints the surviving array [1, 4] and leaves a intact. splice() prints the removed elements [2, 3] and mutates b down to [1, 4] — the returned values are opposites.
const a = [1, 2, 3, 4];
console.log(a.toSpliced(1, 2));
console.log(a);
const b = [1, 2, 3, 4];
console.log(b.splice(1, 2));
console.log(b);Inserting many values and negative starts
Without the spread, the whole array lands in a single slot. Negative start counts from the end, and a start equal to length inserts at the tail — the immutable equivalent of push().
const base = [1, 4];
const middle = [2, 3];
console.log(base.toSpliced(1, 0, middle)); // array as one element
console.log(base.toSpliced(1, 0, ...middle)); // spread to insert both
console.log(base.toSpliced(-1, 0, 99)); // before the last element
console.log(base.toSpliced(base.length, 0, 5)); // append
Discussion