【发布时间】:2021-08-26 10:13:05
【问题描述】:
这与我在使用 Redux Saga 生成器时遇到的问题有关。他们对call 的定义之一是(不包括实现):
// this is taken from redux saga and cannot be changed
function call<Fn extends (...args: any[]) => any>(
fn: Fn,
...args: Parameters<Fn>
): CallEffect<SagaReturnType<Fn>> { ... }
我试图这样称呼它:
function test<F extends (a: string, b: number) => any>(f: F) {
return call(f, 'a', 0)
}
此时我得到错误:'["a", 0]' 类型的参数不可分配给'Parameters
但如果F 扩展(a: string, b: number) => any,那不应该是可赋值的吗?
【问题讨论】:
-
如果我没看错,所有参数都必须是相同的类型才能赋值。只有可以相互分配的类型,例如,如果参数都是特定接口的,它可以工作。解决此问题的方法是在运行时手动检查每个参数的类型。
-
如果您不能更改
call或test的调用签名,那么您将需要类型断言或扩展,因为编译器无法进行高阶分析以当F是未解析的泛型类型时,确定(...a: Parameters<F>)=>ReturnType<F>)可以替代F。 Here 是我看到的选项;这些对你有用吗?如果是这样,我很乐意写一个答案。 -
我无法更改
call签名,它来自redux saga,但我可以更改test。真正的call函数返回一个值并从Fn推断返回类型。扩大或断言会导致真正的返回类型丢失并被any替换。所以我想我只剩下test<R>(f: (a: string, b: number) => R) -
@fredrik 如果类型不同,参数将返回一个元组。即:
type F = (a: string, b: number) => boolean,type P = Parameters<F>给出type P = [a: string, b: number]
标签: typescript typescript-generics