我正在尝试使用带有ES6承诺的TypeScript实现蓝鸟的Promise.method
等效。
所需用法:
const stringify = promiseMethod(JSON.stringify)
stringify(/* ... */) //Type checking available here, returns Promise<string>
最近的实现:
const promiseMethod = function<T, U> (fn: (T) => U) {
if (typeof fn !== "function") {
throw new TypeError("Parameter is not a function:" + fn);
}
return <(T) => Promise<U>>function () {
try{
var value = fn.apply(this, arguments);
return Promise.resolve(value);
}
catch (error){
return Promise.reject(error);
}
};
};
上述实现的问题是呼叫站点期望有很多参数。
如果我将参数和返回类型更改为Function
,则可以获取可编译代码,但是对于参数或返回类型没有类型信息。
没有办法以100%类型的方式执行此操作(Afaik!请指出我错过了什么。(
在一个完美的世界中,打字稿将支持使用类型参数来支持整个参数列表。因此,您可以这样做:
function promiseMethod<T,R>(fn: (...args: T) => R) {
但这是不允许的。您能做的最好的是(...args: Array<any>)
,这很la脚。
(有关此功能有一些讨论,请参见此处和此处的GitHub问题。(
您可以采用大锤方法并超载promiseMethod
功能,例如:
function promiseMethod<R>(fn: () => R): () => Promise<R>;
function promiseMethod<R,A>(fn: (a: A) => R): (a: A) => Promise<R>;
function promiseMethod<R,A,B>(fn: (a: A, b: B) => R): (a: A, b: B) => Promise<R>;
// etc...
function promiseMethod<R>(fn: (...args: Array<any>) => R) {
// implementation
}
这可能满足您的需求,但确实有一些问题:
- 您仍然可以用比您的巨型超额载荷更多地调用
promiseMethod
,而在这种情况下的打字将是漏洞的。 - 如果
fn
本身有过载,也漏水(请参见下文(。
仍然比...args: Array<any>
好。许多常用的库(例如lodash(使用此模式,因为缺乏任何更好的替代方案。
如果要传递的功能有超载...祝您好运。打字稿对功能超载的支持很浅(似乎是设计(。如果您在不调用它的情况下参考过载函数(例如,通过将其传递到promiseMethod
函数作为回调(,则编译器似乎仅使用定义过载的最后(?(的类型签名,然后将其扔掉。不太好。当然,这只会在实际传递超载功能时才会咬您。
最后,我的看法。除非您将大型JS代码库升级到Typescript,否则如果可能的话,我将完全避免避免承诺模式。尤其是现在完全支持async
/await
(由于TS 2.1(,我认为没有用。