The example above is from https://yarnpkg.com/en/package/plura#currydestructed but that package doesn’t seem to be maintained unfortunately.

Curious to hear your thoughts on this :)

It’s an excellent question. And forgive me if I repeat things we already know. I want to make sure I understand the question. And sometimes that means stating the obvious.

As Calle points out, combining currying with destructuring is tricky. JavaScript sees an object as a single value. So our ordinary curry function doesn’t work. To make the problem concrete, let’s look at that add() example again.

const add = ({a, b, c}) => a + b + c;

Under normal circumstances, there’s no need to curry that function, as it only takes one parameter. At least, that’s how the computer sees it. But a human can look at that signature and see three named parameters. Getting the computer to do the same though is trickier. So Richard has done something really interesting here with Plura and curryDestructured().

Having a look at the source code is enlightening. What he’s doing is converting the function to a string. And then he parses it with a regular expression to create a map of the parameters it needs. With that in place, he can track which parameters have been filled in each time the function is called.

Now, that’s a lot of effort just to curry destructured object parameters. But if someone has already done the work for you, then why not go ahead and use it? If you can follow along with the source code, then there’s no reason not to rip out the 2–3 functions needed to make it work. You can keep them in your own personal toolkit and use as necessary. They will continue to work whether someone maintains the project or not.

If you’ve read (and understood) the source code, then you’ll be able to see some of the limitations of it. For example, it looks like that code will only work on functions that you can convert to a string. For example, the following might cause you problems:

That fooAdd() function doesn’t retain the function signature. So this approach of parsing the function string won’t work. That’s OK, so long as you know that going in.

Personally, I haven’t come across many cases where I’d want to use destructured currying. Think about what currying does. It takes polyadic (multi-parameter) functions and makes them unary (single-parameter) functions. But a function that expects an object is already unary. And there are other ways to manipulate objects before we pass them into a function.

To think it through, let’s look at that add() example again. Imagine we have an object with a set to 2 and another object with b set to 3. We want to create a function that takes an object with c set to something and adds them together. One way would be to use curryDestructured(). But I can achieve a similar effect with Object.assign or the spread operator.

It is a little bit more work than curryDestructured() but not much more. Either way, we still have to keep track of how many parameters we’ve applied. Otherwise, we don’t know when we can call the final function.

But, that curryDestructured() interface is still pretty nice… Maybe we could have our cake and eat it too. What if we created a new function that will work even when we can’t call .toString() on the function? The only caveat is that we’ll have to tell currying function which keys we need ahead of time. It might look something like this:

Of course, this is limited too. We’re assuming only flat objects. Writing a version that worked with nested destructuring might be a bit tricker.

So, in summary, currying destructured arguments doesn’t seem like a bad thing to want to do. But I think you can achieve the same effect with assign(). And that approach seems more robust because we’re not relying on .toString(). If that’s still too inconvenient, then we can write a robust destructured curry function that relies on us specifying which keys are needed. It’s not quite as flexible, but it’s pretty close.