Currying in JavaScript

Currying explained simply with a few examples.

The name "currying", coined by Christopher Strachey in 1967[citation > needed], is a reference to logician Haskell Curry.

This guy has a language and a programming technique named after him!

The basic idea of currying

In simple terms, a curried function is a function that returns a function. Currying is generally good when you want to prepopulate a function, like shown in the examples below.

In JavaScript, curried function looks something like this:

function add(x) {
  return function (y) {
    return x + y
  }
}
 
add(1)(1) // 2

But currying syntax somehow clicks together with arrow functions:

const add = x => y => x + y
 
add(1)(1) // 2

JavaScript is cool, it can access the first function’s params in the inner function like nothing.

Calling a curried function

If you want to call a curried function you do it like this:

const one = add(1)
const two = one(1)
console.log(two) // 2

You’re adding into it as you go.

Or:

add(1)(1)

A curried API call example

Here’s a more realistic scenario, something that might happen in everyday work life. A curried function where the outer function can be prepopulated with a URL, and the inner function takes the required options:

// highlight-next-line
// The curried function lives in a shared directory
const getData = url => async options => {
  const params = new URLSearchParams(options)
  const response = await fetch(`${url}?${params.toString()}`)
 
  return response.json()
}
 
// highlight-next-line
// Prepopulate it with different API endpoints
const getEmployees = getData('https://hub.dummyapis.com/employee')
const getProducts = getData('https://hub.dummyapis.com/products')
 
;(async () => {
  // highlight-next-line
  // Call the second half of the curried functions with needed options
  const employees = await getEmployees({ noofRecords: 2 })
  const products = await getProducts({ noofRecords: 3, currency: 'usd' })
 
  console.log({ employees, products })
})()

Play around with a working demo:

Edit cyrrying-test CodeSandbox

Currying a callback function

For example in React you get to deal with events and callback functions a lot.

In the following example that clickHandler fn takes an event and an id:

const Foo = ({ id }) => {
  // highlight-next-line
  const handleClick = (event, id) => {
    if (event.target.id === id) {
      // something...
    }
  }
 
  return (
    // highlight-next-line
    <button id='foo' onClick={event => handleClick(event, id)}>
      Click
    </button>
  )
}

You can write it more concisely by currying the handleClick callback, the click event will be passed to the innermost function:

const Foo = ({ id }) => {
  // highlight-next-line
  const handleClick = id => event => {
    if (event.target.id === id) {
      // something...
    }
  }
 
  return (
    <button id='foo' onClick={handleClick(id)}>
      Click
    </button>
  )
}

That’s purely cosmetic though, I can understand if someone finds that to be a bit extra.

Other examples

A random example of currying: styled-components syntax assumes currying when extending components while using the style object syntax:

const RedParagraph = styled(Paragraph)({
  color: 'red',
})

Conclusions

You can probably sail your JavaScript career through without ever writing a curried function, but in some cases it feels very elegant.

Hope this was helpful, thanks for perusing my little blog article!