[英]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?
在 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();
}
我見過的所有承諾定義文件都聲明承諾的“解決”方法必須接受一個值。 這是最近的一個來自奇妙的絕對類型項目的例子:
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。
但是,如果我想要一個沒有值的承諾,所以我希望能夠在不傳遞值的情況下調用 resolve() 呢? 我可以這樣聲明我的承諾: new Promise<void>
但是我仍然被迫調用 resolve 並傳入某種值。 我可以調用resolve(undefined)
,但這讀起來有點奇怪。
似乎沒有辦法在 Typescript 中正確捕捉這個概念:“如果這個泛型的類型是‘void’,那么不要期望這個函數有一個參數。”
我能做的最接近的是在 resolve 方法中將結果標記為可選,但這意味着結果始終是可選的,即使對於 Promise 的類型版本也是如此。
從您想要使用 Promise 接口的方式來看,您似乎希望有時傳遞一個值,有時您不想傳遞任何值,這就是可選參數的用途。 如果解決帶有“未定義”結果的承諾是不可接受的(IMO 這不是一個壞主意,這確切地說明了代碼中發生的事情 - 承諾的結果是udefined)我可以提出一個似乎就是你的解決方案尋找:
我會為承諾定義一個“合同”,讓我們說:
export interface IMyPromiseResult {
result: number;
}
並將其與承諾一起使用:
new Promise<IMyPromiseResult>((resolve)=>{
resolve(<IMyPromiseResult>{ result: 5 });
resolve(<IMyPromiseResult>{ });
}
雖然這種方法有點復雜,但它打開了一些有趣的選項......另一方面 - 當前的絕對類型 Promise 構造函數定義為:
constructor(callback: (resolve: (result?: R) => void, reject: (error: any) => void) => void);
所以有一個可選的結果是允許的,你應該沒問題。
我可能剛剛想出了一個我滿意的解決方法。 在這里我想有一個的情況下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);
}
}
在這種情況下,我可以像這樣使用它:
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 )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.