To remove an item from an array in TypeScript, use filter() when you want a new array without the value, and splice(index, 1) when you want to remove it from the array you already have. shift() drops the first element, pop() drops the last, and delete should be avoided because it leaves an empty slot behind. This guide runs every method, removes items by value, by index and by property, keeps the types correct while filtering, and shows the two bugs that catch almost everyone.
Every example was compiled and run with TypeScript 5.2.2 and Node.js v22.22.2 in the Windows Command Prompt, with tsc --target es2022 --lib es2023,dom --strict file.ts and then node file.js. The output below is the real output. Reference: Array.prototype.splice() on MDN.
Remove an item from an array in TypeScript
Four methods cover nearly every case. The first returns a new array; the other three change the original:
const cities: string[] = ["Austin", "Denver", "Seattle", "Boston"];
const withoutDenver = cities.filter(city => city !== "Denver"); // new array
console.log(withoutDenver);
cities.splice(2, 1); // remove 1 element at index 2, in place
console.log(cities);
console.log("removed first:", cities.shift(), "->", cities);
console.log("removed last: ", cities.pop(), "->", cities);
Output:
[ 'Austin', 'Seattle', 'Boston' ]
[ 'Austin', 'Denver', 'Boston' ]
removed first: Austin -> [ 'Denver', 'Boston' ]
removed last: Boston -> [ 'Denver' ]
filter() builds a new array; splice(), shift() and pop() edit this one.| What you want to remove | Use | Changes the original? |
|---|---|---|
| A value, wherever it is | arr.filter(x => x !== value) | No |
| The first match, in place | arr.splice(arr.indexOf(value), 1) | Yes |
The element at index i | arr.splice(i, 1) | Yes |
The element at index i, new array | arr.toSpliced(i, 1) | No |
| The first element | arr.shift() | Yes |
| The last element | arr.pop() | Yes |
| Everything | arr.length = 0 | Yes |
Remove an element from an array by value
filter() removes every matching element and hands back a new array, which is what you want for React state or any value someone else might be holding. indexOf() plus splice() removes only the first match, in place:
const tags: string[] = ["react", "node", "typescript", "node"];
// new array: removes EVERY match, original untouched
console.log(tags.filter(tag => tag !== "node"));
// in place: removes only the FIRST match
const index = tags.indexOf("node");
if (index !== -1) tags.splice(index, 1);
console.log(tags);
// the trap: indexOf returns -1 when the value is missing
const missing = tags.indexOf("vue");
console.log("indexOf('vue') =", missing);
tags.splice(missing, 1); // splice(-1, 1) removes the LAST element
console.log("after splice(-1, 1):", tags);
Output:
[ 'react', 'typescript' ]
[ 'react', 'typescript', 'node' ]
indexOf('vue') = -1
after splice(-1, 1): [ 'react', 'typescript' ]
indexOf() returned -1, and splice(-1, 1) removed the wrong element.That is the mistake worth remembering. indexOf() returns -1 when the value is not in the array, and splice() treats a negative index as counting back from the end, so it quietly deletes the last element. Always check index !== -1 before you splice.
Remove an element by index with splice()
splice() takes the start index and how many elements to remove, and it returns the removed elements rather than the array. toSpliced() is the ES2023 version that leaves the original alone; it needs "lib": ["es2023", "dom"] and Node.js 20 or later. There is a full walkthrough of the method in our guide to the TypeScript array splice() method:
const steps: string[] = ["Pick items", "Weigh box", "Pack box", "Print label", "Ship"];
const removed = steps.splice(1, 1); // returns what it removed
console.log(removed, steps);
steps.splice(1, 2); // a range: 2 elements from index 1
console.log(steps);
steps.splice(-1, 1); // negative index counts from the end
console.log(steps);
const plan: string[] = ["Pick items", "Pack box", "Ship"];
console.log(plan.toSpliced(1, 1), plan); // ES2023: new array, original kept
Output:
[ 'Weigh box' ] [ 'Pick items', 'Pack box', 'Print label', 'Ship' ]
[ 'Pick items', 'Ship' ]
[ 'Pick items' ]
[ 'Pick items', 'Ship' ] [ 'Pick items', 'Pack box', 'Ship' ]
Remove an object from an array of objects
With objects you match on a property, not on the object itself, because two objects with the same contents are still different references. findIndex() is the indexOf() of object arrays, and a Set of ids removes many at once. See also working with arrays of objects in TypeScript:
interface Order {
id: string;
customer: string;
total: number;
}
const orders: Order[] = [
{ id: "ORD-1001", customer: "Emma", total: 249.99 },
{ id: "ORD-1002", customer: "Michael", total: 89.5 },
{ id: "ORD-1003", customer: "Olivia", total: 430 },
];
const kept: Order[] = orders.filter(order => order.id !== "ORD-1002");
console.log(kept.map(o => o.id));
const position = orders.findIndex(order => order.id === "ORD-1003");
if (position !== -1) orders.splice(position, 1);
console.log(orders.map(o => o.id));
const cancelled = new Set(["ORD-1001", "ORD-9999"]); // remove several at once
console.log(orders.filter(order => !cancelled.has(order.id)).length, "left");
Output:
[ 'ORD-1001', 'ORD-1003' ]
[ 'ORD-1001', 'ORD-1002' ]
1 left
Keep the types right while filtering
Removing undefined or null is the one place TypeScript pushes back. On TypeScript 5.2, the compiler does not know that the filter removed the empty values:
const rawTotals: (number | undefined)[] = [249.99, undefined, 430];
const totals: number[] = rawTotals.filter(total => total !== undefined);
console.log(totals);
tsc output:
filter_narrow.ts(3,7): error TS2322: Type '(number | undefined)[]' is not assignable to type 'number[]'.
Type 'number | undefined' is not assignable to type 'number'.
Type 'undefined' is not assignable to type 'number'.
(number | undefined)[].A type predicate, (total): total is number, tells the compiler what survives. TypeScript 5.5 and later work this out on their own, so you can drop the annotation once you upgrade. Filtering arrays in TypeScript covers more of these patterns, and there are dedicated guides for removing empty strings and removing undefined values:
const rawTotals: (number | undefined)[] = [249.99, undefined, 430];
// a type predicate tells the compiler what survives the filter
const totals: number[] = rawTotals.filter((total): total is number => total !== undefined);
console.log(totals, totals.reduce((sum, t) => sum + t, 0).toFixed(2));
const rawNames: (string | null)[] = ["Emma", null, "", "Olivia"];
const names: string[] = rawNames.filter((name): name is string => Boolean(name));
console.log(names);
Output:
[ 249.99, 430 ] 679.99
[ 'Emma', 'Olivia' ]
Do not use delete on an array
delete arr[1] removes the value but not the slot. The length stays the same and you are left with a hole that behaves differently in every loop, as we show in looping through an array:
const scores: number[] = [90, 72, 88];
delete scores[1]; // does NOT remove the slot
console.log(scores, "length:", scores.length);
console.log("scores[1] is", scores[1]);
const fixed: number[] = [90, 72, 88];
fixed.splice(1, 1); // really removes it
console.log(fixed, "length:", fixed.length);
Output:
[ 90, <1 empty item>, 88 ] length: 3
scores[1] is undefined
[ 90, 88 ] length: 2
delete leaves <1 empty item> and keeps the length at 3; splice() really removes it.Remove all items: clearing an array
arr.length = 0 empties the array itself, so every reference to it sees the change. Assigning a new [] only re-points your variable and leaves the old array intact for everyone else, which is a classic source of “why is my cart still full” bugs. Clearing an array while preserving its type goes into the typing details:
const queue: string[] = ["a", "b", "c"];
const alsoQueue = queue; // another name for the SAME array
queue.length = 0; // empties the array itself
console.log(queue, alsoQueue);
let basket: string[] = ["x", "y"];
const oldBasket = basket;
basket = []; // only re-points the variable
console.log(basket, oldBasket);
const box: string[] = ["p", "q", "r"];
console.log(box.splice(0, box.length), box); // empty it and keep what was inside
Output:
[] []
[] [ 'x', 'y' ]
[ 'p', 'q', 'r' ] []
Removing items inside a loop
Removing while you iterate forwards skips elements, because everything after the removed item shifts down one place. Loop backwards, or simply build a new array with filter(), which is both safer and shorter. If duplicates are the reason you are removing things, use the duplicate-removal methods instead:
const queue: string[] = ["keep", "drop", "drop", "keep"];
queue.forEach((item, i) => { if (item === "drop") queue.splice(i, 1); });
console.log("forEach + splice:", queue); // one "drop" survived
const backwards: string[] = ["keep", "drop", "drop", "keep"];
for (let i = backwards.length - 1; i >= 0; i--) {
if (backwards[i] === "drop") backwards.splice(i, 1);
}
console.log("backwards loop: ", backwards);
const source: string[] = ["keep", "drop", "drop", "keep"];
console.log("filter: ", source.filter(item => item !== "drop"));
Output:
forEach + splice: [ 'keep', 'drop', 'keep' ]
backwards loop: [ 'keep', 'keep' ]
filter: [ 'keep', 'keep' ]
filter() or splice(): which is faster?
Removing half of 50,000 numbers, one pass of filter() against a backwards loop full of splice() calls:
function time(label: string, fn: () => number): void {
const start = performance.now();
const left = fn();
console.log(label.padEnd(26), (performance.now() - start).toFixed(1).padStart(8), "ms", "left", left);
}
const size = 50_000;
const make = (): number[] => Array.from({ length: size }, (_, i) => i);
time("filter (one pass)", () => make().filter(n => n % 2 === 0).length);
time("splice in a loop", () => {
const a = make();
for (let i = a.length - 1; i >= 0; i--) if (a[i] % 2 !== 0) a.splice(i, 1);
return a.length;
});
splice() shifts the rest of the array.Each splice() has to move every element after the one it removed, so removing many items that way is quadratic work. Use splice() for a single element and filter() when you are removing a set of them.
More TypeScript array guides you may want next:
- Add or append elements to an array
- Loop through an array in TypeScript
- Sort an array of objects by property
- Check if an array contains a value
- Check if an array is null or empty
Frequently asked questions
How do I remove an item from an array in TypeScript?
Use arr.filter(item => item !== value) for a new array without it, or arr.splice(index, 1) to remove it from the existing array.
How do I remove an element by value?
Find it first: const i = arr.indexOf(value); if (i !== -1) arr.splice(i, 1);. Skipping the -1 check deletes the last element instead.
How do I remove an object from an array of objects?
Match on a property: orders.filter(o => o.id !== "ORD-1002"), or findIndex() plus splice() to remove it in place.
Why should I not use delete to remove an array element?
delete clears the value but keeps the slot, so the length does not change and you get a hole. Use splice() or filter().
How do I remove all items from an array in TypeScript?
Set arr.length = 0. Assigning arr = [] only changes your variable; anything else holding the old array still sees the items.
How do I remove undefined or null values and keep the type?
Use a type predicate: arr.filter((v): v is string => v !== undefined). TypeScript 5.5 and later infer this for you.
What does splice() return?
An array of the elements it removed, not the array you called it on. arr.splice(1, 1) gives you [removedItem].
Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn