🧩 Pattern Matching, Currying & Co: The Modern JavaScript You Should Know in 2025
JavaScript isn’t the same language it was a few years ago.
From pattern matching to currying, optional chaining, and pipeline operators, the language is evolving fast — and modern JS developers are expected to keep up.
If you still think var and == are the only quirks in JS, this post is your 2025 refresh. ⚡
Let’s explore the modern JavaScript features that make your code cleaner, faster, and smarter.
🧠 1️⃣ Pattern Matching — Switch Statements, Reinvented
Pattern matching is like a smarter, cleaner switch statement that’s finally making its way to JavaScript (currently in Stage 3 of TC39).
Here’s how it looks 👇
const user = { type: 'admin', name: 'Lakshita' };
match (user) {
when ({ type: 'admin' }) => console.log('Welcome, admin!');
when ({ type: 'guest' }) => console.log('Welcome, guest!');
when (_) => console.log('Hello, stranger!');
}✅ Why it’s awesome:
- Matches objects, arrays, or values structurally
- No more deep
if...elseor nestedswitchtrees - Clean, readable, and expressive
💡 Think of it as pattern-based destructuring with conditions — the next evolution of JavaScript control flow.
⚡ 2️⃣ Currying — The Secret Sauce of Functional JS
Currying transforms a function that takes multiple arguments into a chain of functions, each taking one argument.
Here’s a simple example 👇
// Normal function
function add(a, b) {
return a + b;
}
// Curried version
const curriedAdd = a => b => a + b;
console.log(curriedAdd(5)(3)); // ✅ 8Now you can partially apply arguments and reuse functions like a pro 👇
const add10 = curriedAdd(10);
console.log(add10(5)); // ✅ 15
console.log(add10(20)); // ✅ 30✅ Why it’s awesome:
- Reusability and modularity
- Cleaner function composition
- Powerful in frameworks like React, Redux, and RxJS
💡 Currying is the foundation of functional programming — and modern JS is leaning more functional every year.
🪄 3️⃣ Optional Chaining — The “Don’t Crash Me” Operator
Before 2020, this line could crash your code 👇
console.log(user.profile.address.city);If user or profile was undefined, boom 💥 — TypeError.
Now with optional chaining:
console.log(user?.profile?.address?.city);✅ Why it’s awesome:
- Cleaner null checks
- No need for deep
iftrees - Perfect for nested data (e.g., APIs, JSON)
💡 Combine it with nullish coalescing (??) to add fallback values:
const city = user?.profile?.address?.city ?? 'Unknown City';🔁 4️⃣ Pipeline Operator (|>) — Functional Magic Made Readable
This one is a game changer (currently Stage 2).
It lets you pipe data through functions in a clean, readable way — just like in Unix or functional languages.
Get Lakshika’s stories in your inbox
Join Medium for free to get updates from this writer.
Without pipelines 👇
const result = capitalize(reverse(trim(" hello world ")));With pipelines 👇
const result = " hello world "
|> trim
|> reverse
|> capitalize;✅ Why it’s awesome:
- Linear, readable data flow
- No more nested function calls
- Makes functional code beautiful
💡 Works great with functional libraries like Ramda or lodash/fp.
🧩 5️⃣ Object Destructuring & Rest/Spread Magic
Still writing code like this?
const name = user.name;
const age = user.age;Use destructuring instead 👇
const { name, age } = user;You can even use rest/spread for cloning or extending:
const user = { name: 'Alex', age: 25, role: 'admin' };
const { role, ...details } = user;
console.log(details); // ✅ { name: 'Alex', age: 25 }✅ Why it’s awesome:
- Shorter code
- Easier object manipulation
- Safer immutability
🧬 6️⃣ Immutable Data Patterns — Write Safe Code
Mutating state can lead to sneaky bugs — especially in React and Redux.
Instead of changing objects directly 👇
user.age = 30; // ❌ Bad practiceDo this 👇
const updatedUser = { ...user, age: 30 }; // ✅ Immutable updateOr freeze it completely 👇
Object.freeze(user);✅ Why it’s awesome:
- Predictable state
- Fewer side effects
- Easier debugging
🧠 7️⃣ Async/Await + Promise.allSettled — Modern Async Handling
Async/await made JS cleaner, but now we have Promise.allSettled() for resilient async code.
const results = await Promise.allSettled([
fetch("/api/user"),
fetch("/api/posts"),
fetch("/api/comments")
]);
results.forEach(r => console.log(r.status));✅ Why it’s awesome:
- Handles all promises (even failed ones)
- Great for concurrent API calls
💡 Combine it with try/catch and top-level await in modern ES2023 modules.
🚀 Final Thoughts
JavaScript keeps evolving — and the devs who stay current code smarter, not harder.
Features like pattern matching, currying, and pipelines are shaping the next-gen JS syntax that’s both expressive and elegant.
So if your JS still looks like it’s from 2015, it’s time for a refactor. ✨
“Old JavaScript walks so modern JavaScript can fly.” 🦋
🏁 TL;DR — Modern JS You Should Know
A message from our Founder
Hey, Sunil here. I wanted to take a moment to thank you for reading until the end and for being a part of this community.
Did you know that our team run these publications as a volunteer effort to over 3.5m monthly readers? We don’t receive any funding, we do this to support the community. ❤️
If you want to show some love, please take a moment to follow me on LinkedIn, TikTok, Instagram. You can also subscribe to our weekly newsletter.
And before you go, don’t forget to clap and follow the writer️!








