通用 curry 函数的打字稿类型

Typescript Typings for generic curry functions

我正在尝试更好地使用 FP,但在如何处理通用“curry”函数方面遇到困难。

例如,我写了一个“Curry”版本的 reduce:

const reduce = <S, R>(fn: (result: R, obj: S, i?: number, arr?: S[]) => R, init: R) => 
(objects: S[]) => 
objects.reduce(fn, init);

const numToSum: number[] = [1,2,3,5,8,13];

const result = reduce((sum, n) => sum + n, 0)(numToSum);

问题是打字稿显然不能知道 S 的类型,直到你用 numToSum.

实际调用 curry 函数

当你看到没有 curry 调用时更明显:

const sumNumbersFn = reduce((sum, n) => sum + n, 0);

在这种情况下,您可以通过使用 n: number 键入函数本身的参数或显式设置通用参数 <number[], number>.

来解决此问题

前者似乎是合理的,但我 运行 的是,随着事情变得越来越复杂,我不得不不断地提供通用签名。

我想知道我是否遗漏了什么,实际上可以让打字稿从后面的函数调用中“推断”出类型吗?

回到第一个例子:

const result = reduce((sum, n) => sum + n, 0)(numToSum);

似乎编译器实际上应该具有推断类型所需的所有信息。

也许我的类型不对?

更新

这是我 运行 遇到的问题的更多 concrete/full 示例

TS-Playground

您所要做的就是将 select 中的 return 函数声明为通用函数:

function select<T, S>(sFn: (obj: T) => S) {
  function computation<G>(fn: (obj: S) => G) {
    return (obj: T) => fn(sFn(obj));
  }

  return computation;
} 

P.S:我不知道为什么这种语法在 TS playground 中不起作用:

const select = <T, S>(sFn: (obj: T) => S) => <G>(fn: (obj: S) => G) => {
  return (obj: T) => fn(sFn(obj));
}

可能是因为一些 TS 配置设置。因此,我将解决方案编写为函数声明而不是函数表达式。