如何在Typescript中声明泛型承诺,以便在泛型类型为“时”&书信电报;无效>&引用;,其中一种方法赢得了';不接受参数?

如何在Typescript中声明泛型承诺,以便在泛型类型为“时”&书信电报;无效>&引用;,其中一种方法赢得了';不接受参数?,typescript,definitelytyped,Typescript,Definitelytyped,在Typescript中,我希望能够以这样一种方式定义承诺的类型,以便我可以这样做: //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>((

在Typescript中,我希望能够以这样一种方式定义承诺的类型,以便我可以这样做:

//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();
}
//这在今天起作用:
新承诺((决议)=>{
//酷
决心(5);
//错误,因为我没有传递号码:
解决();
}
//这也是我想做的:
新承诺((决议)=>{
//错误,因为我传递了一个值:
决心(5);
//很酷,因为我声明promise为void类型,所以resolve不接受值:
解决();
}
我看到的承诺定义文件都声明承诺的“resolve”方法必须采用一个值。这是来自奇妙的DefiniteTypted项目的最新示例:

declare class Promise<R> implements Thenable<R> {
    constructor(callback: (resolve : (result: R) => void, reject: (error: any) => void) => void); 
///...
}
declare类承诺实现了该表{
构造函数(回调:(解析:(结果:R)=>void,拒绝:(错误:any)=>void)=>void);
///...
}
```

这基本上是说,“resolve回调必须传递一个类型为R的值。”对于像
new promise
这样的承诺来说,这很好。Typescript将验证我们使用类型为
number
的值调用resolve

但是,如果我想要一个没有值的承诺,那么我希望能够在不传递值的情况下调用resolve(),我可以这样声明我的承诺:
newpromise
但我仍然被迫调用resolve并传入某种类型的值。我可以调用
resolve(未定义)
,但这读起来有点奇怪

似乎无法在Typescript中正确捕获此概念:“如果此泛型具有“void”类型,则不要期望此函数具有参数。”


我能做的最接近的事情是在resolve方法中将结果标记为可选的,但这意味着结果始终是可选的,即使对于承诺的类型版本也是如此。

从您希望使用承诺接口的方式来看,您似乎有时希望传递值,有时不希望传递值,所以这就是可选参数R是给你的。 如果解决带有“未定义”结果的承诺是不可接受的(在我看来,这不是一个坏主意,这可以很好地说明代码中发生了什么-承诺的结果是被定义的),我可以提出一个解决方案,这似乎正是您想要的:

我会为承诺定义一个“合同”,比如:

export interface IMyPromiseResult {
    result: number;
}
并承诺使用它:

new Promise<IMyPromiseResult>((resolve)=>{

   resolve(<IMyPromiseResult>{ result: 5 });

   resolve(<IMyPromiseResult>{ });
}
因此,有一个可选结果是允许的,您应该对此很满意。

我可能刚刚想出了一个我很满意的解决方法。如果我希望有一个
承诺
来确保
resolve
回调不带参数,而不是让resolve方法总是带一个可选参数,I c可以这样定义一个新类:

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);
    }
}
导出类VoidPromise扩展了RSVP.Promise{
//请注意,“解析”在此处不接受参数:
构造函数(回调:(解析:()=>void,拒绝:(错误:any)=>void)=>void){
超级(回调);
}
}
在这种情况下,我可以这样使用它:

    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"));
                }
            })
        });
    }
公共静态testVoidPromise():VoidPromise{ 返回新的作废承诺((解决、拒绝)=>{ 设置超时(1000,()=>{ if(Math.random()<0.5){ //请注意,resolve()不接受参数 解决(); }否则{ 拒绝(新错误(“出错”); } }) }); } 诚然,开发人员将不得不使用VoidPromise而不是简单的“Promise”,但是在不必将resolve参数错误地标记为可选参数的情况下实现了预期效果

对于我的场景,上面的代码比将所有
resolve
方法标记为具有可选结果更符合我的期望。在99%的情况下,将所有结果标记为可选会感到危险。如果它总是可选的,我可以声明一个
Promise
,调用
resolve()
没有结果,并为我的承诺获得一个
未定义的结果。在这种情况下,我应该拒绝承诺。我不相信resolve方法的参数真的是可选的。(来源:)

这确实有效!
用户需要支持这样一个用例


Runnable示例太长,无法发布。但只需将最新定义和承诺代码复制/粘贴到编辑器中,您就会看到您的示例现在起作用了。

感谢您花时间回答Slawek。是的,这听起来似乎是可选的。我真的更喜欢这样一种结构:,“此变量是可选的,但仅适用于具有X类型的承诺”,但我认为可选非常简单,并且接近我的意图。您提供的链接现在已断开。
    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"));
                }
            })
        });
    }