如何在打字稿中键入3个参数的咖喱函数?

时间:2018-11-14 23:52:43

标签: javascript typescript iterator currying

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

我正在尝试创建一个咖喱函数,但是在定义重载方面遇到了麻烦。具体来说,如果您使用一个参数调用parallelMap,则可以使用1或2个参数调用下一个参数。但是,def被标记为无效。

  

[ts]重载签名与函数实现不兼容。 [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)
}

谢谢!

1 个答案:

答案 0 :(得分:2)

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

  

[编译器]查看重载列表,然后进行第一次重载尝试以提供的参数调用该函数。如果找到匹配项,它将选择此重载作为正确的重载。

您的前两个重载具有相同的参数类型,因此将永远不会使用第二个重载。这意味着如果您使用一个参数调用parallelMap(),它将返回一个两个参数的函数。它不返回单参数函数。

让我们补救。这里的解决方案是,当您使用一个参数调用parallelMap()时,您想返回一个重载函数,而不是仅一个参数或两个参数的函数。

此外,您还希望泛型类型参数位于返回的函数上,因为当您调用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> 
}

现在说“如果您使用一个参数调用parallelMap(),它将返回另一个可以用XXX和YYY类型的两个参数调用的函数并返回ZZZ,也可以使用一个参数输入XXX,然后将函数从YYY返回到ZZZ。”

现在它应该可以正常工作了。请注意,由于您正在使用重载,因此以下代码并不完全正确:

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

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

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

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

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

相关问题