Practical Examples of Currying in JavaScript

Currying is a functional programming technique that transforms a multi-argument function into a sequence of single-argument functions, improving modularity and reusability.
In this blog, we explore 6 real-world examples of currying in JavaScript.
👉 For a deeper dive into the theory behind currying, check out our companion blog — Functional Programming in JavaScript: Partial Application and currying
Practical Examples of Currying
Below are practical examples demonstrating how currying can be applied in real-world JavaScript scenarios.
Example 1: Formatting Log Messages
Currying creates reusable logging functions for different log levels.
const formatLog = level => message => `[${level}] ${message}`;
const logError = formatLog('ERROR');
const logInfo = formatLog('INFO');
console.log(logError('Connection failed')); // [ERROR] Connection failed
console.log(logInfo('User logged in')); // [INFO] User logged in
Explanation: The formatLog
function is curried to first accept a level
, then a message
, creating specialized functions like logError
.
Example 2: Dynamic Discount Calculator
Currying simplifies creating functions for specific discount percentages.
const discount = percent => price => price * (1 - percent / 100);
const tenPercentOff = discount(10);
const twentyPercentOff = discount(20);
console.log(tenPercentOff(100)); // 90
console.log(twentyPercentOff(100)); // 80
Explanation: discount
is curried to fix the percentage, creating reusable functions for specific discounts.
Example 3: DOM Manipulation
Currying streamlines DOM updates by pre-configuring element selectors.
const updateElemText = id => content => (document.querySelector(`#${id}`).textContent = content);
const updateHeaderText = updateElemText('header');
updateHeaderText('Hello World');
// HTML: <div><h1 id="header">Hello World</h1></div>
Explanation: The curried function specializes in updating a specific DOM element’s text.
Example 4: Operation-Based Calculator
Create a curried function that performs different operations based on a parameter.
const calculate = operation => a => b => {
if (operation === 'sum') return a + b;
if (operation === 'multiply') return a * b;
if (operation === 'divide') return a / b;
if (operation === 'subtract') return a - b;
return 'Invalid Operation';
};
console.log(calculate('sum')(2)(4)); // 6
console.log(calculate('multiply')(2)(4)); // 8
Explanation: The function takes an operation type and two numbers, performing the specified operation in a curried manner.
Example 5: Infinite Argument Summation
Handle an arbitrary number of arguments using recursion.
const sum = a => b => b !== undefined ? sum(a + b) : a;
console.log(sum(1)(2)(3)()); // 6
console.log(sum(1)(2)(3)(4)()); // 10
Step-by-Step Explanation:
Define the Curried Function:
sum
is defined as a curried function using arrow functions. It takes an initial argumenta
and returns a function that expectsb
.Check for
b
: Ifb
is provided (i.e., notundefined
), the function returns a newsum
function with the accumulated valuea + b
. This enables recursive calls for more arguments.Base Case: When
b
isundefined
(e.g.,sum(1)(2)(3)()
), the function returns the accumulated valuea
.Execution Example:
sum(1)
returns a function witha = 1
, expectingb
.sum(1)(2)
computesa + b = 1 + 2 = 3
, returns a newsum
witha = 3
.sum(1)(2)(3)
computesa + b = 3 + 3 = 6
, returns a newsum
witha = 6
.sum(1)(2)(3)()
hasb = undefined
, so it returnsa = 6
.For
sum(1)(2)(3)(4)()
, the process continues until()
returns1 + 2 + 3 + 4 = 10
.
Example 6: Generic Curry Function
Convert any function into a curried version.
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func(...args);
}
return (...next) => curried(...args, ...next);
};
}
const join = (a, b, c) => `${a}_${b}_${c}`;
const curriedJoin = curry(join);
console.log(curriedJoin(1, 2, 3)); // '1_2_3'
console.log(curriedJoin(1)(2, 3)); // '1_2_3'
console.log(curriedJoin(1, 2)(3)); // '1_2_3'
Step-by-Step Explanation:
Define the Curry Function: The
curry
function takes a functionfunc
and returns acurried
function that handles arguments.Check Argument Count:
curried
uses the spread operator (...args
) to collect arguments. If the number of arguments (args.length
) is at least the number required byfunc
(func.length
), it callsfunc
with all arguments.Return New Function: If fewer arguments are provided,
curried
returns a new function that collects additional arguments (...next
) and combines them withargs
for the next call.Execution Example:
curriedJoin(1, 2, 3)
:args = [1, 2, 3]
,func.length = 3
, sojoin(1, 2, 3)
is called, returning'1_2_3'
.curriedJoin(1)
:args = [1]
, fewer than 3, returns a function expecting more arguments.curriedJoin(1)(2, 3)
: Combinesargs = [1]
withnext = [2, 3]
, callsjoin(1, 2, 3)
, returns'1_2_3'
.curriedJoin(1, 2)(3)
: First call storesargs = [1, 2]
, second call adds3
, callsjoin(1, 2, 3)
, returns'1_2_3'
.
Thanks for checking out the blog! 🙌
Tried out the examples? Let me know how it went or drop your favourite use case for currying in the comments!
Subscribe to my newsletter
Read articles from Deepthi Purijala directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Deepthi Purijala
Deepthi Purijala
Full Stack Developer with hands-on experience of more than 1 year. Proficient in both Back-end and Front-end technologies, with a strong commitment to delivering high-quality code