🧠 Mastering Functional Programming in JavaScript: Compose, Pipe, and Currying

Functional Programming (FP) can feel overwhelming at first—but once you get the hang of it, you’ll write cleaner, more reusable, and testable JavaScript code.
In this article, we’ll break down three core FP concepts:
compose
pipe
currying
Let’s understand each with simple code examples and analogies.
🔁 compose
: Right-to-Left Function Chaining
🧾 What is compose
?
compose
is a utility that chains functions together. It runs functions from right to left, passing the output of one function into the next.
🧠 Analogy
Imagine you’re getting ready:
Wear shoes
Put on socks
Take a shower
Now, to actually get ready, you'd:
- Shower ➝ then Socks ➝ then Shoes
That’s right to left — like compose
.
🧪 Example
const toUpper = (str) => str.toUpperCase();
const exclaim = (str) => `${str}!`;
const greet = (name) => `Hello, ${name}`;
const compose = (...fns) => (value) =>
fns.reduceRight((acc, fn) => fn(acc), value);
const welcome = compose(exclaim, toUpper, greet);
console.log(welcome("pushpesh")); // ➝ HELLO, PUSHPESH!
🔄 pipe
: Left-to-Right Function Chaining
🔄 What is pipe
?
Just like compose
, but left to right. This feels more natural when reading code.
📖 Analogy
Back to our morning routine:
Shower
Socks
Shoes
That’s the exact order you follow — and that’s pipe.
🧪 Example
const pipe = (...fns) => (value) =>
fns.reduce((acc, fn) => fn(acc), value);
const welcomePipe = pipe(greet, toUpper, exclaim);
console.log(welcomePipe("pushpesh")); // ➝ HELLO, PUSHPESH!
🧩 Currying: One Argument at a Time
🔍 What is Currying?
Currying turns a function that takes multiple arguments into a chain of functions, each taking one argument.
🧠 Analogy
Ordering coffee:
Step 1: Choose coffee type (
latte
)Step 2: Choose size (
medium
)Step 3: Choose milk (
oat
)
You can customize each step along the way.
🧪 Example
// Normal
function add(a, b) {
return a + b;
}
// Curried
function curriedAdd(a) {
return function (b) {
return a + b;
};
}
console.log(curriedAdd(2)(3)); // ➝ 5
🔁 Reusability with Currying
const add2 = curriedAdd(2);
console.log(add2(10)); // ➝ 12
console.log(add2(100)); // ➝ 102
🎯 Why Should You Care?
🧼 Clean, declarative code
🔁 Easy function reuse
🧪 Better testability
🔄 Encourages immutability
🧰 Bonus: Build Your Own compose
, pipe
, curry
// Compose (Right to Left)
const compose = (...fns) => (value) =>
fns.reduceRight((acc, fn) => fn(acc), value);
// Pipe (Left to Right)
const pipe = (...fns) => (value) =>
fns.reduce((acc, fn) => fn(acc), value);
// Curry (2-arg)
const curry = (fn) => (a) => (b) => fn(a, b);
🏁 Final Thoughts
You don’t need to master all of functional programming to benefit from it. Start small:
Use
pipe
to make transformations more readable.Use
compose
when chaining logic in reverse makes more sense.Use
currying
to create flexible, reusable functions.
Once these become second nature, you'll feel like you're playing with Lego blocks—snapping together small, powerful pieces to build great apps.
💬 Over to You
Have you used compose
or currying
in a real project? Or found it confusing? Let me know in the comments — let’s learn together.
Subscribe to my newsletter
Read articles from pushpesh kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
