是否可以为装饰器功能(我是指装饰器设计模式装饰器,而不是打字稿装饰器功能)编写类型签名?
我尝试过:
function decorate<T extends () => any>(callback: T): T {
return (...args) => {
console.log('called with args: ', args);
return callback(...args);
};
}
但是它给了我TS2322: Type '(...args: any[]) => any' is not assignable to type 'T'.
答案 0 :(得分:0)
您可以在{3.0中使用Tuples in rest parameters and spread expressions
function decorate<A extends any[], R>(callback: (...a: A) => R): (...a: A) => R {
return (...args) => {
console.log('called with args: ', args);
return callback(...args);
};
}
function foo(s: number) {
return s.toString();
}
function bar(s: number, o : string[]) {
return s.toString();
}
var dBar = decorate(bar) // (s: number, o: string[]) => string
var dFoo = decorate(foo) // (s: number) => string
有一些注意事项,如评论中所指出。泛型不适用于这种方法。另外,上面的函数不能正确处理重载。有关过载问题的解决方法,请参见this answer。
修改
一种版本,可以减少警告,但在实现中需要一些类型断言,该版本与您建议的版本很接近:
function decorate<T extends (...a: any[]) => any>(callback: T): T {
return ((...args) => {
console.log('called with args: ', args);
return callback(...args);
}) as any;
}
这可以更好地说明输入与输出相同,如果不需要对返回类型或参数进行其他类型的操作,则最好使用该输入。尽管此版本破坏了实现类型的安全性,但要获得完全的呼叫站点安全性,这是可以接受的折衷方案,因为它将与重载和泛型一起使用。