你如何在打字稿中输入一个三参数柯里化函数?

How do you type a 3 argument curried function in typescript?

或者如何为一个返回函数定义多个签名

我正在尝试制作柯里化函数,但我在定义重载方面遇到了问题。具体来说,如果您使用一个参数调用 parallelMap,则可以使用 1 个或 2 个参数调用下一个参数。但是 def 被标记为无效。

[ts] Overload signature is not compatible with function implementation. [2394]

export function parallelMap<T, R> (concurrency: number): (func: (data: T) => R | Promise<R>) => (iterable: AnyIterable<T>) => AsyncIterableIterator<R>

完全实施;

export function parallelMap<T, R> (concurrency: number): (func: (data: T) => R | Promise<R>, iterable: AnyIterable<T>) => AsyncIterableIterator<R>
export function parallelMap<T, R> (concurrency: number): (func: (data: T) => R | Promise<R>) => (iterable: AnyIterable<T>) => AsyncIterableIterator<R>
export function parallelMap<T, R> (concurrency: number, func: (data: T) => R | Promise<R>): (iterable: AnyIterable<T>) => AsyncIterableIterator<R>
export function parallelMap<T, R> (concurrency: number, func: (data: T) => R | Promise<R>, iterable: AnyIterable<T>): AsyncIterableIterator<R>
export function parallelMap<T, R> (
  concurrency: number,
  func?: (data: T) => R | Promise<R>,
  iterable?: AnyIterable<T>,
) {
  if (func === undefined) {
    return <A, B>(curriedFunc: (data: A) => B | Promise<B>, curriedIterable?: AnyIterable<A>) => parallelMap(concurrency, curriedFunc, curriedIterable)
  }
  if (iterable === undefined) {
    return (curriedIterable: AnyIterable<T>) => parallelMap<T, R>(concurrency, func, curriedIterable)
  }
  return _parallelMap<T, R>(concurrency, func, iterable)
}

谢谢!

当不同的参数类型应导致不同的 return 类型时,

Overloads 很有用。拥有两个具有相同参数类型的不同重载签名是没有用的。那是因为,正如手册所说:

[The compiler] looks at the overload list, and proceeding with the first overload attempts to call the function with the provided parameters. If it finds a match, it picks this overload as the correct overload.

您的前两个重载具有相同的参数类型,因此绝不会使用第二个重载。这意味着如果你用一个参数调用 parallelMap(),它将 return 一个双参数函数,仅此而已。它不是 return 单参数函数。

让我们补救一下。这里的解决方案是当你用一个参数调用 parallelMap() 时,你想要 return 一个重载函数,而不是只有一个参数或两个参数的函数.

此外,您希望泛型类型参数位于 returned 函数上,因为当您调用 parallelMap(concurrency) 时您不知道 TR 最终会成为。

所以用这个替换前两个签名:

export function parallelMap(concurrency: number): { 
  <T,R>(func: (data: T) => R | Promise<R>, iterable: AnyIterable<T>): AsyncIterableIterator<R>, 
  <T,R>(func: (data: T) => R | Promise<R>): (iterable: AnyIterable<T>) => AsyncIterableIterator<R> 
}

现在说 "if you call parallelMap() with one argument, it will return another function which can be called with two arguments of type XXX and YYY and return ZZZ, and it can also be called with one argument of type XXX and return a function from YYY to ZZZ."

现在应该基本可以使用了。请注意,由于您使用的是重载,因此以下代码并不完全正确:

  if (func === undefined) {
    return <A, B>(
      curriedFunc: (data: A) => B | Promise<B>, 
      curriedIterable?: AnyIterable<A>
    ) => parallelMap(concurrency, curriedFunc, curriedIterable) // error!
  }

毕竟,none 的重载调用签名可能接受 undefined 第三个参数。您可以使用两个或三个定义的参数来调用它。所以你应该将其更改为:

  if (func === undefined) {
    return <A, B>(
      curriedFunc: (data: A) => B | Promise<B>,
      curriedIterable?: AnyIterable<A>
    ) => curriedIterable ?
        parallelMap(concurrency, curriedFunc, curriedIterable) :
        parallelMap(concurrency, curriedFunc)
  }

根据是否定义 curriedIterable 调用 parallelMap() 的两个不同重载。

好的,希望对您有所帮助。祝你好运!