7

I can create a generic currying function for functions with a set number of arguments. IE)

function curry2<T1,T2,R>(func:(arg1:T1, arg2:T2) => R, param2: T2):(arg:T1) => R{
    return (param1:T1) => func(param1, param2);
};

However, I cannot find a (typesafe) way to implement a generic curry function for a function with any number of arguments. In a different language I would name all my currying functions (ie: curry1, curry2, curry3, etc) the same thing (curry) and then have function overloading do the work of running the correct implementation of curry. However, typescript does not allow function overloading like this.

It isn't too bothersome to have to write curry2/curry1/curry3 everywhere instead of a single unified interface of curry, but if there is a way to do it I would appreciate knowing how!

Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
gnicholas
  • 2,041
  • 1
  • 21
  • 32
  • 1
    Looks like you can't: https://github.com/Microsoft/TypeScript/issues/212, https://github.com/Microsoft/TypeScript/issues/1773 – Ry- Sep 11 '16 at 02:16
  • Womp. This is what I thought but thanks anyways. – gnicholas Sep 11 '16 at 02:21
  • This is not JavaScript. There are no issues with JavaScript and overloading, because JavaScript does not have overloading. The [tag:javascript] tag is not appropriate here. – Amadan Sep 13 '16 at 01:19
  • @Ryan The second link you give is about variadic generics, which is a different thing. The first is about typing as related to `bind` and `apply`, but that isn't directly relevant here either. –  Sep 13 '16 at 02:50
  • You are trying to "curry" in the second argument? AFAIK that is not "currying". For the cases of three or more arguments, are you trying to partially apply the last argument? –  Sep 13 '16 at 02:52
  • @torazaburo: I know; I figured if `bind` can't do it, `bind` minus one feature probably can't either. Also, variadic generics sound like very much the same thing. – Ry- Sep 13 '16 at 04:07
  • Variadic generics refer to a variable number of **types**, such as `function foo<...T>`, which doesn't exist. Here we are dealing with a variable number of **parameters**. –  Sep 13 '16 at 05:01

2 Answers2

2

It isn't too bothersome to have to write curry2/curry1/curry3 everywhere instead of a single unified interface of curry,

You can with overloading (doc https://basarat.gitbooks.io/typescript/content/docs/types/functions.html)

More

Something to get you started:

function curry<T1,T2,R>(func:(arg1:T1, arg2:T2) => R, param2: T2):(arg:T1) => R;
function curry<T1,T2,T3,R>(func:(arg1:T1, arg2:T2, arg3: T3) => R, param2: T2):(arg:T1) => R;
function curry(){
    // Implement
    return undefined;
};
basarat
  • 261,912
  • 58
  • 460
  • 511
  • This is not true. error TS2393: Duplicate function implementation. error TS2393: Duplicate function implementation. EDIT: I guess I said that too quickly. It appears that you can declare a function without a body. Which is kind of cool. – gnicholas Sep 14 '16 at 01:25
0

The example of basarat is quite good but the second overload does not seem to be correct. This is what I came up with, when writing a type signature for a curry function:

interface curry {
    <T1, T2, R>(func: (p1: T1, p2: T2) => R): (p: T1) => (p: T2) => R;
    <T1, T2, T3, R>(func: (p1: T1, p2: T2, p3: T3) => R): (p: T1) => (p: T2) => (p: T3) => R;
    <T1, T2, T3, T4, R>(func: (p1: T1, p2: T2, p3: T3, p4: T4) => R): (p: T1) => (p: T2) => (p: T3) => (p: T4) => R;
    <T1, T2, T3, T4, T5, R>(func: (p1: T1, p2: T2, p3: T3, p4: T4, p5: T5) => R): (p: T1) => (p: T2) => (p: T3) => (p: T4) => (p: T5) => R;
}

And of course you can repeat it with more parameters until you reach a safe depth :)

// the actual curry function implementation ommited
var makeCurry: curry = <any> null;

// example function that we would like to curry, with two parameters
var getInfo = (age: number, name: string) => {
    return `${name} is ${age} years old`;
}

// the previous function curried
var getInfoCurried = makeCurry<number, string, string>(getInfo);

var info = getInfoCurried(26)('Gergo');
gsanta
  • 754
  • 6
  • 21