我试图创建一个函数,它接受一个函数作为参数,并返回一个与传入函数行为相同的函数(作为一些更复杂的业务逻辑的核心)。
// a function that returns a function that behaves
// in the same way as the passed in function.
export function create<T extends Function>(func: T): T {
function run(...args: any[]) {
// Later I plan on doing some stuff here...
return func(...args);
// ...and here
}
return run;
}
const source = (n:number) => n.toString();
const created = create(source);
字符串
上面的代码工作了,我在created()
(const created: (n: number) => string
)上得到了正确的类型注解和完成,但是typescript抱怨说,
Type '(. args:any[])=> any'不能赋值给类型' T '.'(... args:any[])=> any'可以赋值给类型' T '的约束,但是'T'可以用约束' Function '的不同子类型示例化。
这条信息对我来说有点费解。你能帮我理解它并建议一些方法来解决这个问题吗?谢谢!!
1条答案
按热度按时间m1m5dgzv1#
像这样的呼叫签名的问题是,
字符串
它声明返回一个与
func
输入完全相同类型的值,不管是什么。Functions in JavaScript是一级对象,也可以像其他对象一样拥有属性。所以你可以这样做:型
这里
source
是一个具有字符串值prop
属性的函数。但是create()
的实现并没有尝试确保func
的每个属性都复制到输出中。因此编译器警告您,尽管返回的函数肯定是Function
,它可能不是T
。如果忽略该错误,则可能发生以下问题:型
编译器会很高兴地允许你访问
create.prop
,因为create(source)
应该返回与create
完全一样的东西。传统的方法是只显式地关心输入的调用签名,而不是整个输入类型:也就是说,你希望函数在参数类型
A
和返回类型R
的列表中是generic:型
现在编译时没有错误。你仍然可以将带有额外属性的函数传递到
create()
中,但是现在输出值不会假装有这些额外属性,所以你会得到一个编译器错误,这将帮助你避免运行时错误:型
Playground链接到代码