Ryan
Ryan

Reputation: 6347

How to add types to a curried function in TypeScript?

In the following snippet of code where I have declared a curried add method.

const add = (a: number) => {
  return (b?: number) => {
    return (b === undefined ? a : add(a + b))
  }
}

This works fine if I call this with the following arguments: add(1)()

But typescript throws the following error when I call it like this: add(1)(2)()

Cannot invoke an expression whose type lacks a call signature. Type 'number | ((b?: number) => number | ...)' has no compatible call signatures.

What do I need to add to enable typed usage of this method?

Upvotes: 0

Views: 128

Answers (1)

jcalz
jcalz

Reputation: 330571

I would describe the type of add() as the following Add type:

type Add = (a: number) => Add2;
type Add2 = ((b: number) => Add2) & (() => number);

The Add function type takes a number and returns an Add2.

The Add2 function type is an overloaded function which returns a different type depending on the number and type of arguments that come in. It's also self-referential: if you call an Add2 with a number parameter, you get an Add2 out.

You more or less need to use assertions to convince the compiler that your add() is a valid Add:

const add = ((a: number) => (b?: number) =>
  b === undefined ? a : add(a + b)) as Add;

And then you should be able to use it as expected:

const x = add(1)(2)(3)(); // number
console.log(x); // 6

Link to code

Okay, hope that helps; good luck!

Upvotes: 2

Related Questions