How to Remove an Item from an Array in TypeScript

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' ]
Command Prompt showing a TypeScript file compiled with tsc and run with node, removing items from an array of cities with filter, splice, shift and pop
filter() builds a new array; splice(), shift() and pop() edit this one.
What you want to removeUseChanges the original?
A value, wherever it isarr.filter(x => x !== value)No
The first match, in placearr.splice(arr.indexOf(value), 1)Yes
The element at index iarr.splice(i, 1)Yes
The element at index i, new arrayarr.toSpliced(i, 1)No
The first elementarr.shift()Yes
The last elementarr.pop()Yes
Everythingarr.length = 0Yes

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' ]
Command Prompt output showing filter removing every match while indexOf and splice remove the first, and splice minus one removing the last element by mistake
The last two lines are the bug: 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'.
Command Prompt showing TypeScript error TS2322 because filtering undefined values still produces an array that may contain undefined
The values are gone at runtime, but the type still says (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
Command Prompt output comparing delete leaving an empty slot in a TypeScript array with splice removing the element and shortening the array
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;
});
Command Prompt output timing filter in one pass against splice inside a loop removing 25,000 elements from a TypeScript array
One pass beats repeated splicing: every 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:

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].