在Typescript中,我希望能够以这样的方式定义Promise的类型,以便我可以这样做:
//This works today:
new Promise<number>((resolve)=>{
//Cool
resolve(5);
//Error, because I didn't pass a number:
resolve();
}
//This is what I want to do also:
new Promise<void>((resolve)=>{
//Error, because I passed a value:
resolve(5);
//Cool, because I declared the promise to be of type void, so resolve doesn't take a value:
resolve();
}
我见过的promise定义文件都声明promise的“resolve”方法必须带一个值。 Here是精彩的DefinitelyTyped项目的最新示例:
declare class Promise<R> implements Thenable<R> {
constructor(callback: (resolve : (result: R) => void, reject: (error: any) => void) => void);
///...
}
```
基本上说,“解析回调必须传递一个R类型的值。”这对于像new Promise<number>
这样的承诺来说很好。 Typescript将验证我们是否使用number
类型的值调用resolve。
但是,如果我想要一个没有值的promise,那么我希望能够在不传递值的情况下调用resolve()?我可以这样声明我的承诺:new Promise<void>
但是后来我仍然被迫调用resolve并传入某种值。我可以打电话给resolve(undefined)
,但这听起来有点奇怪。
似乎无法在Typescript中正确捕获此概念:“如果此泛型具有'void'类型,则不要指望此函数的参数。”
我能做的最接近的是在resolve方法中将结果标记为可选,但这意味着结果始终是可选的,即使对于Promises的类型版本也是如此。
答案 0 :(得分:4)
这确实有效!
promise definitions为updated以支持此类用例。
Runnable示例太长,无法发布。但只需将最新的定义和Promise代码复制/粘贴到编辑器中,您就会看到您的示例现在有效。
答案 1 :(得分:2)
从你想要使用Promise接口的方式来看,你似乎希望有时传递一个值,有时你想不传递任何值,这就是可选参数的用途。 如果使用&#39; undefined&#39;解决承诺?结果是不可接受的(IMO这不是一个坏主意,这可以告诉我代码中发生了什么 - 承诺的结果是 udefined)我可以提出一个看似你正在寻找的解决方案为:
我会定义一份合同&#39;对于承诺,让我们说:
export interface IMyPromiseResult {
result: number;
}
并将其与承诺一起使用:
new Promise<IMyPromiseResult>((resolve)=>{
resolve(<IMyPromiseResult>{ result: 5 });
resolve(<IMyPromiseResult>{ });
}
虽然这种方法有点复杂,但它会打开一些有趣的选项...... 另一方面 - 当前的DefinitelyTyped Promise构造函数定义为:
constructor(callback: (resolve: (result?: R) => void, reject: (error: any) => void) => void);
因此允许使用可选结果,你应该没问题。
答案 2 :(得分:2)
我可能刚刚提出了一个我很满意的解决方法。如果我想要Promise<void>
确保resolve
回调不获取参数,而不是让resolve方法始终采用可选参数,我可以像这样定义一个新类:
export class VoidPromise extends RSVP.Promise<void>{
//Note that resolve does not take a parameter here:
constructor(callback:(resolve:() => void, reject:(error:any) => void) => void){
super(callback);
}
}
在这种情况下,我可以像这样使用它:
public static testVoidPromise() : VoidPromise{
return new VoidPromise((resolve, reject)=>{
setTimeout(1000, ()=>{
if (Math.random() < 0.5){
//Note that resolve() does NOT take a parameter
resolve();
}else{
reject(new Error("Something went wrong"));
}
})
});
}
当然,开发人员必须使用VoidPromise而不是简单的“Promise”,但实现了预期的效果,而不必将resolve参数错误地标记为可选。
对于我的场景,上面的代码符合我的期望,而不是将所有 resolve
方法标记为具有可选结果。将所有结果标记为可选项在99%的情况下感觉很危险。如果它始终是可选的,我可以声明Promise<number>
,在没有结果的情况下调用resolve()
,并为我的承诺获得undefined
结果。在那种情况下,我应该拒绝承诺。我不相信解析方法的参数是真正可选的。 (来源:https://github.com/domenic/promises-unwrapping#the-promise-constructor)