如何在 Typescript 中声明泛型 Promise,以便当泛型类型为“<void>”时,其方法之一不接受参数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24555636/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I declare a Generic Promise in Typescript, so that when the Generic type is "<void>", one of its methods won't take a parameter?
提问by Taytay
In Typescript, I want to be able to define a Promise's type in such a way so that I can do this:
在 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();
}
The promise definition files I've seen all declare that the "resolve" method of a promise must take a value. Hereis a recent example from the wonderful DefinitelyTyped project:
我见过的所有承诺定义文件都声明承诺的“解决”方法必须接受一个值。这是最近的一个来自奇妙的绝对类型项目的例子:
declare class Promise<R> implements Thenable<R> {
constructor(callback: (resolve : (result: R) => void, reject: (error: any) => void) => void);
///...
}
```
``
That basically says, "The resolve callback must be passed a value of type R." That's fine for a promise like new Promise<number>
. Typescript will verify we're calling resolve with a value of type number
.
这基本上是说,“解析回调必须传递一个 R 类型的值。” 对于像new Promise<number>
. Typescript 将验证我们正在使用 type 值调用 resolve number
。
However, what if I want a promise that doesn't have a value, so I want to be able to call resolve() without passing a value? I can declare my promise like this: new Promise<void>
But then I'm still forced to call resolve and pass in a value of some sort. I can call resolve(undefined)
, but that reads a bit strangely.
但是,如果我想要一个没有值的承诺,所以我希望能够在不传递值的情况下调用 resolve() 呢?我可以这样声明我的承诺:new Promise<void>
但是我仍然被迫调用 resolve 并传入某种值。我可以调用resolve(undefined)
,但这读起来有点奇怪。
There appears to be no way to properly capture this concept in Typescript: "If this generic has a type 'void', then don't expect a parameter for this function."
似乎没有办法在 Typescript 中正确捕捉这个概念:“如果这个泛型的类型是‘void’,那么不要期望这个函数有一个参数。”
The closest I can do is mark the result as optional in the resolve method, but that would mean that the result is alwaysoptional, even for typed versions of Promises.
我能做的最接近的是在 resolve 方法中将结果标记为可选,但这意味着结果始终是可选的,即使对于 Promise 的类型版本也是如此。
采纳答案by Taytay
I mighthave just come up with a workaround I'm pleased with. In the case where I want to have a Promise<void>
that ensures the resolve
callback does nottake a parameter, rather than making the resolve method always take an optional parameter, I can define a new class like so:
我可能刚刚想出了一个我满意的解决方法。在这里我想有一个的情况下Promise<void>
,确保了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);
}
}
And in that case, I can use it like so:
在这种情况下,我可以像这样使用它:
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"));
}
})
});
}
Granted, devs will have to use the VoidPromise instead of simply "Promise", but the intended effect is achieved without having to falsely mark the resolve parameter as optional.
当然,开发人员将不得不使用 VoidPromise 而不是简单的“Promise”,但无需错误地将 resolve 参数标记为可选参数即可实现预期效果。
For my scenario, the above code meets my expectations more than marking allresolve
methods as having an optional result. Marking allresults as optional feels dangerous in the 99% case. If it's always optional, I can declare a Promise<number>
, call resolve()
without a result, and get an undefined
result for my promise. In that case, I should have rejected the promise. I don't believe it is expected that the resolve method's parameter is truly optional. (Source: https://github.com/domenic/promises-unwrapping#the-promise-constructor)
对于我的场景,上面的代码比将所有resolve
方法标记为具有可选结果更符合我的期望。在 99% 的情况下,将所有结果标记为可选的感觉很危险。如果它总是可选的,我可以声明一个Promise<number>
,resolve()
没有结果的调用,并undefined
为我的承诺获得一个结果。在那种情况下,我应该拒绝承诺。我不相信解析方法的参数是真正可选的。(来源:https: //github.com/domenic/promises-unwrapping#the-promise-constructor)
回答by Anders
This do work!
The promise definitionswere updatedto support such a use case.
Runnable example is too long to be posted. But just copy/paste newest definitions and your Promise code into a an editor and you will see that your example now works.
Runnable 示例太长,无法发布。但是只需将最新的定义和您的 Promise 代码复制/粘贴到编辑器中,您就会看到您的示例现在可以工作了。
回答by Slawek
From the way you want to use the Promise interface it seems that you want to sometimes pass a value and sometimes you want to pass no value, so thats what optional parameters are for. If resolving a promise with 'undefined' result is not acceptable (IMO this isnt a bad idea, this tells exacly what is going on in the code - the result of promise isudefined) I can propose a solution that seems to be what you are looking for:
从您想要使用 Promise 接口的方式来看,您似乎希望有时传递一个值,有时您不想传递任何值,这就是可选参数的用途。如果解决具有“未定义”结果的承诺是不可接受的(IMO 这不是一个坏主意,这确切地说明了代码中发生的事情 - 承诺的结果是udefined)我可以提出一个似乎就是你的解决方案寻找:
I would define a 'contract' for the promise, lets say:
我会为承诺定义一个“合同”,让我们说:
export interface IMyPromiseResult {
result: number;
}
and the use it with the promise:
并将其与承诺一起使用:
new Promise<IMyPromiseResult>((resolve)=>{
resolve(<IMyPromiseResult>{ result: 5 });
resolve(<IMyPromiseResult>{ });
}
While this approach is a bit more complicated, it opens some interesting options... On the other hand - current DefinitelyTyped Promise constructor is defined as:
虽然这种方法有点复杂,但它打开了一些有趣的选项......另一方面 - 当前的绝对类型 Promise 构造函数定义为:
constructor(callback: (resolve: (result?: R) => void, reject: (error: any) => void) => void);
so having an optional result is allowed and you should be fine with it.
所以有一个可选的结果是允许的,你应该没问题。