Here is a pattern that shows up in almost every codebase:
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.
How findLast() works
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:
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.
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.
findLastIndex() for when you need the position
findLast() returns the element. findLastIndex() returns its index — useful when you need to slice, splice, or reference the position rather than the value:
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():
transactions.findLastIndex(t => t.type === 'refund'); // -1
🎮 Try it yourself
▶️ Open the interactive playground →
Runs right in your browser — poke at it and watch the concept react live.
Real-world patterns
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:
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:
const lastUndoable = history.findLast(entry => entry.undoable);
Form field arrays. Finding the last populated row in a dynamic form:
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 types
TypeScript has typed findLast() and findLastIndex() since version 4.9 — the same release that added the satisfies operator. The return type mirrors find():
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.
Browser support
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.
🧠 Test yourself
Think it clicked? Take the 6-question quiz →
Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.
The takeaway
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:
- ⭐ GitHub — follow me and star the projects: github.com/parsajiravand
- 📸 Instagram — frontend best practices, daily: @bestpractice___
- 💼 LinkedIn — linkedin.com/in/parsa-jiravand
- ✉️ Email (work & contract inquiries): bestpractice2026@gmail.com
Top comments (0)