或者如何为返回的函数定义多个签名
我正在尝试创建一个柯里化(Currying)函数,但我在定义重载方面遇到了问题。具体来说,如果您调用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)
}
谢谢!
最佳答案
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()
如果只有一个参数,它将返回一个有两个参数的函数,仅此而已。它不返回单参数函数。
让我们来解决这个问题。这里的解决方案是当您调用parallelMap()
时对于一个参数,您希望返回一个重载函数,而不是只有一个参数或只有两个参数的函数。
此外,您希望泛型类型参数位于返回的函数上,因为当您调用 parallelMap(concurrency)
时那时你不知道什么T
和R
最终将成为。
因此将前两个签名替换为:
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
已定义。
好的,希望有帮助。祝你好运!
关于javascript - 如何在 typescript 中输入 3 参数柯里化(Currying)函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53310509/