← blog
JavaScriptAugust 14, 2026 · 3 min read

You copy and reverse the array to find the last match. findLast() searches from the end directly.

The usual workaround — `[...arr].reverse().find()` — allocates a full copy just to walk it backward. ES2023 added `findLast()` and `findLastIndex()` to search from the end without touching the original.

Parsa Jiravand · Frontend engineer · building bestpractic
You copy and reverse the array to find the last match. `findLast()` searches from the end directly.

Here is a pattern that shows up in almost every codebase:

JavaScript
const lastActive = [...users].reverse().find(u => u.status === 'active');

It works. But it creates a full copy of the array, reverses that copy in place, and then walks it from the start. All to get one element near the end. The bigger the array, the more wasteful this is — and the less obvious the intent becomes to the next reader.

ES2023 added findLast() to handle this directly.

findLast() takes the same callback as find() — a predicate that receives the current element, its index, and the array — but it starts at the last index and works backward:

JavaScript
const lastActive = users.findLast(u => u.status === 'active');

The original array is not copied. It is not reversed. The method walks backward in a single pass and returns the first element for which the predicate returns true — which is the last such element from the array's perspective.

JavaScript
1
2
3
4
5
6
7
8
9
const transactions = [ { id: 1, type: 'credit', amount: 100 }, { id: 2, type: 'debit', amount: 40 }, { id: 3, type: 'credit', amount: 200 }, { id: 4, type: 'debit', amount: 75 }, ]; const lastCredit = transactions.findLast(t => t.type === 'credit'); // { id: 3, type: 'credit', amount: 200 }

Like find(), it returns undefined if no element matches.

findLast() returns the element. findLastIndex() returns its index — useful when you need to slice, splice, or reference the position rather than the value:

JavaScript
1
2
3
4
5
const lastCreditIndex = transactions.findLastIndex(t => t.type === 'credit'); // 2 // Example: everything from the last credit onward const tail = transactions.slice(lastCreditIndex);

When no element matches, findLastIndex() returns -1, matching the behavior of findIndex():

JavaScript
transactions.findLastIndex(t => t.type === 'refund'); // -1

Runs right in your browser — poke at it and watch the concept react live.

Audit logs and event histories. You often want the most recent event matching a condition — the last failed login, the last status change, the last error before a success:

JavaScript
1
2
3
4
const lastFailure = auditLog.findLast(e => e.level === 'error'); if (lastFailure) { showErrorBanner(lastFailure.message); }

Undo stacks. Finding the most recent reversible operation without rebuilding the stack:

JavaScript
const lastUndoable = history.findLast(entry => entry.undoable);

Form field arrays. Finding the last populated row in a dynamic form:

JavaScript
1
2
const lastFilledIndex = rows.findLastIndex(row => row.value.trim() !== ''); const rowsToSubmit = rows.slice(0, lastFilledIndex + 1);

In all of these, the intent — "the most recent X that satisfies Y" — maps directly onto findLast. The [...arr].reverse().find() workaround buries that intent behind three operations.

TypeScript has typed findLast() and findLastIndex() since version 4.9 — the same release that added the satisfies operator. The return type mirrors find():

TypeScript
1
2
3
4
5
6
7
8
9
10
11
12
interface User { id: number; status: 'active' | 'inactive'; } const users: User[] = [...]; const last = users.findLast(u => u.status === 'active'); // type: User | undefined const lastIndex = users.findLastIndex(u => u.status === 'active'); // type: number

No extra configuration needed. The types live in lib.es2023.array.d.ts and are included automatically when your tsconfig targets ES2023 or later — or when you add "ES2023" to your lib array explicitly.

findLast() and findLastIndex() are Baseline 2022: Chrome 97 (January 2022), Firefox 104 (August 2022), Safari 15.4 (March 2022). Node.js has supported them since version 18. There is nothing to install and no polyfill needed for any actively maintained runtime.

Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.

Search your codebase for reverse().find( and reverse().findIndex(. Each one is a findLast() or findLastIndex() in disguise — wrapped in a copy that exists only to flip the direction. Replace them and the intent reads directly: start from the end, return the first match you find.

find() and findIndex() search from the front. findLast() and findLastIndex() search from the back. They're symmetric, they're in every modern runtime, and there's no longer a reason to reach for the workaround.


Thanks for reading! Let's stay connected:

Keep reading

Originally published on dev.to