Skip to content Skip to footer

Spicing Up Your JavaScript: A Dive into Currying 🌶️

Alright, folks! Buckle up because today we’re diving headfirst into the savory world of currying in JavaScript. Now, before you start thinking about Indian cuisine, let me clarify: we’re talking about a fundamental concept in functional programming that can add a whole new level of flavor to your code.

Currying, in essence, is the process of transforming a function with multiple arguments into a sequence of functions, each taking a single argument. It’s like taking a full meal and breaking it down into bite-sized courses, each delivering its own unique taste.

Why Curry at All?

You might be scratching your head, wondering why you’d want to transform your straightforward multi-argument functions into a series of single-argument ones. The answer is as tasty as it gets: currying allows for more modular and reusable code. It’s like having a spice rack where you can mix and match flavors to create the perfect dish every time.

Basic Currying in Vanilla JavaScript

Let’s start with a simple example to get our taste buds warmed up. Imagine you have a function that adds two numbers:

function add(a, b) {
  return a + b;
}

Now let’s curry this function:

function curryAdd(a) {
  return function(b) {
    return a + b;
  };
}

You can use it like this:

const addFive = curryAdd(5);
console.log(addFive(10)); // Outputs: 15

With curryAdd, we first fix the first number, and then we create a new function that only needs the second number. It’s like prepping your mise en place before the dinner rush – everything is ready to go when you need it.

Currying in the Wild: Lodash

When it comes to currying in JavaScript, Lodash is like the secret sauce. This library has a _.curry method that makes currying as easy as pie. Check out how you can curry the add function with Lodash:

import _ from 'lodash';

const add = (a, b) => a + b;
const curriedAdd = _.curry(add);

console.log(curriedAdd(5)(10)); // Outputs: 15

Lodash handles the currying process for you, so you can focus on the logic of your application rather than the boilerplate of currying functions manually.

Ramda: A Curry Connoisseur’s Delight

For those who are serious about functional programming in JavaScript, Ramda is like the gourmet spice blend of the JavaScript world. Ramda functions are automatically curried, making it a breeze to use this technique.

Here’s how you’d use Ramda to curry our add function:

import R from 'ramda';

const add = R.curry((a, b) => a + b);

const addFive = add(5);
console.log(addFive(10)); // Outputs: 15

With Ramda, currying is part of the package, and you’ll find yourself writing more declarative and functional code without even trying.

Cooking Up a Curry in React

React might seem like an odd place to talk about currying, but it’s actually a match made in heaven. Currying can help you handle events and manage state in a more functional way.

Imagine you have a list of items, and you want to handle a click event for each one:

const ListItem = ({ item, onItemClick }) => (
  <li onClick={() => onItemClick(item.id)}>{item.name}</li>
);

You can curry the onItemClick function to make it cleaner:

const handleItemClick = curry((id, event) => {
  console.log(`Item with ID ${id} was clicked.`);
});

// Usage in a component
<ListItem item={item} onItemClick={handleItemClick(item.id)} />

This keeps your event handlers tidy and focused on what they need to do: respond to the click, not worry about the item’s details.

The Art of Currying in Redux

Redux, the state management powerhouse, can also benefit from a pinch of currying. When you’re creating action creators or middleware, currying can help you keep things DRY and maintainable.

Here’s a simple action creator without currying:

const addItem = (item) => ({
  type: 'ADD_ITEM',
  payload: item
});

And now, let’s add some curry:

const createAction = curry((type, payload) => ({
  type,
  payload
}));

const addItem = createAction('ADD_ITEM');

With this, you can create a variety of action creators with different types but the same structure, all thanks to currying.


We’ve just scratched the surface of the currying concept and its applications in JavaScript. Stay tuned for the second half of this article, where we’ll explore more advanced techniques, including partial application and how to curry your way through asynchronous operations. Get ready to kick your JavaScript skills up a notch with the power of currying!

Welcome back to the flavorful journey of currying in JavaScript! We’ve already seen how currying can transform the way we write and organize our code, making it more modular and easier to reason about. Now, let’s take our currying skills to the next level by exploring advanced techniques and diving into the world of asynchronous operations.

Partial Application vs. Currying

Before we proceed, let’s clear up some common confusion between partial application and currying. They’re like culinary cousins – related but with distinct characteristics.

Partial application is the process of fixing a few arguments to a function, producing another function of smaller arity (number of arguments). Currying, on the other hand, breaks down a function into a series of unary functions (functions with a single argument).

Here’s an example to illustrate partial application:

function multiply(a, b, c) {
  return a * b * c;
}

function partialMultiplyBy5And10(a) {
  return multiply(5, 10, a);
}

console.log(partialMultiplyBy5And10(2)); // Outputs: 100

As you can see, we’ve partially applied the multiply function by fixing the first two arguments.

Currying Asynchronous Functions

Currying isn’t just for synchronous operations. It can also be a powerful ally when dealing with asynchronous code, like API calls or database transactions. Let’s say we have a function to fetch user data based on a user ID, and we want to curry it:

const fetchUserData = curry(async (endpoint, userId) => {
  const response = await fetch(`${endpoint}/${userId}`);
  if (!response.ok) {
    throw new Error('Problem fetching data');
  }
  return response.json();
});

const fetchFromUserApi = fetchUserData('https://api.example.com/users');

// Later in your code
fetchFromUserApi(123).then(userData => {
  console.log(userData);
}).catch(error => {
  console.error(error);
});

By currying the fetchUserData function, we can easily create new functions for specific endpoints without repeating the fetch logic.

Currying with Promises and Async/Await

Currying plays nicely with Promises and async/await syntax, too. Let’s curry a function that returns a Promise:

const delay = curry((time, message) => new Promise(resolve => {
  setTimeout(() => resolve(message), time);
}));

const delayBy1000 = delay(1000);

delayBy1000('Hello after 1 second').then(console.log); // Outputs: Hello after 1 second

We’ve created a delay function that curries the time and message, returning a Promise that resolves after the specified time. With async/await, it looks even cleaner:

async function delayedGreeting() {
  const message = await delayBy1000('Hello with async/await');
  console.log(message);
}

delayedGreeting();

Currying Event Handlers in React

Earlier, we touched on currying event handlers in React. Now, let’s see how we can leverage currying in a more complex scenario with a form submission:

const FormComponent = ({ onFormSubmit }) => {
  const handleSubmit = curry((formData, event) => {
    event.preventDefault();
    onFormSubmit(formData);
  });

  return (
    <form onSubmit={handleSubmit({ name: 'John Doe', age: 30 })}>
      <button type="submit">Submit</button>
    </form>
  );
};

In this example, handleSubmit is a curried function that takes formData and returns a new function expecting the event object. This pattern can be particularly useful when working with forms that have predefined data or when handling complex form structures.

The Power of Curried Reducers

Reducers in Redux are great candidates for currying. By currying reducers, you can create highly reusable and composable update logic. Let’s look at a curried reducer that handles updating the state based on the action type:

const createReducer = curry((initialState, handlers, state = initialState, action) => {
  const handler = handlers[action.type];
  return handler ? handler(state, action) : state;
});

const todoReducer = createReducer(
  { todos: [] },
  {
    ADD_TODO: (state, action) => ({ ...state, todos: [...state.todos, action.payload] }),
    REMOVE_TODO: (state, action) => ({ ...state, todos: state.todos.filter(todo => todo.id !== action.payload) }),
  }
);

// Usage with Redux
const store = createStore(todoReducer);

By currying the createReducer function, we can easily create different reducers with a predefined structure while keeping the state update logic clean and maintainable.


Currying is more than just a programming technique; it’s a mindset that encourages you to think about your code in terms of composition and reusability. Whether you’re dealing with synchronous or asynchronous code, user interfaces, or state management, currying can help you write more expressive and flexible JavaScript.

Next time you’re faced with a complex problem, consider reaching for the spice rack of currying. It might just be the secret ingredient you need to make your code sing. Happy coding, and remember: a little bit of currying can go a long way in the kitchen of JavaScript!