Search code examples
typescriptfunctional-programmingtypescript-typingscurrying

Typescript typings for basic recursively curried function


I'm trying to define a basic function with 2 signatures to allow basic currying without including any complicated 3rd party libraries.

This is the basic function, it takes 2 arguments, if the second argument is not provided it returns a function that takes the last argument, then it will execute the function.

function concat(x, y) {
  if (arguments.length === 1) {
    return (_y) => concat(x, _y);
  }
  return x.concat(y);
}

If I use a separate index.d.ts typescript definition file, I can use the following types.

export function concat<T>(x: T, y: T): T;
export function concat<T>(x: T): (y: T) => T;

However, if I overload the function in a ts file I get typedef errors.

export function concat<T>(x: T, y: T): T;
export function concat<T>(x: T): (y: T) => T {
  if (arguments.length === 1) {
    return (_y) => concat(x, _y);
  }
  return x.concat(y); // Type error: TS2304: Cannot find name 'y'.
}

Is there something I am missing in the type definition inline in the ts file?

function concat(x, y) {
  if (arguments.length === 1) {
    return (_y) => concat(x, _y);
  }
  return x.concat(y);
}

// both args provided
console.log(
  concat(['one'], ['two'])
);

// curried
console.log(
  concat(['one'])(['two'])
);


Solution

  • You've mixed the overload declarations with the implementation. They need to be separate, regardless whether they are in the same file or not:

    export function concat<T>(x: T, y: T): T;
    export function concat<T>(x: T): (y: T) => T;
    export function concat(x, y?) {
      if (arguments.length === 1) {
        return (_y) => concat(x, _y);
      }
      return x.concat(y);
    }