在 TypeScript 的非同步函式中回傳一個 Promise
據我所知,這兩個函數在 JavaScript 中會有相同的行為:
const whatever1 = (): Promise<number> => {
return new Promise((resolve) => {
resolve(4);
});
};
const whatever2 = async (): Promise<number> => {
return new Promise((resolve) => {
resolve(4);
});
};
但 TypeScript 似乎不喜歡第二個,它說:
Type '{}' is not assignable to type 'number'.
這是 TypeScript 的錯誤,還是我對 async 函數有所誤解?
答案#1
這很複雜。
首先,在這段程式碼中
const p = new Promise((resolve) => {
resolve(4);
});
p 的類型被推斷為 Promise<{}>。在 TypeScript 的 GitHub 上有開放的相關問題,因此可以說這是一個 bug,因為很明顯(對人類而言),p 應該是 Promise<number>。
然後,Promise<{}> 與 Promise<number> 是相容的,因為基本上 promise 唯一的屬性是 then 方法,而依據 TypeScript 函數型別相容性規則,then 在這兩種 promise 型別中是相容的。這就是為什麼 whatever1 不會報錯的原因。
但 async 的目的是假裝你在處理的是實際值,而不是 Promise,然後你在 whatever2 中得到錯誤,因為 {} 顯然與 number 不兼容。
所以 async 的行為是相同的,但目前需要一些變通方法才能讓 TypeScript 編譯它。你可以在創建 promise 時簡單地提供明確的泛型參數,如下所示:
const whatever2 = async (): Promise<number> => {
return new Promise<number>((resolve) => {
resolve(4);
});
};
答案#2
當你使用 new Promise((resolve)... 時,推斷的類型是 Promise<{}>,因為你應該使用 new Promise<number>((resolve)。
有趣的是,這個問題只有在加入 async 關鍵字時才被突顯出來。我建議在 GitHub 上向 TS 團隊報告這個問題。
有許多方法可以解決這個問題。以下所有函數的行為都是相同的:
const whatever1 = () => {
return new Promise<number>((resolve) => {
resolve(4);
});
};
const whatever2 = async () => {
return new Promise<number>((resolve) => {
resolve(4);
});
};
const whatever3 = async () => {
return await new Promise<number>((resolve) => {
resolve(4);
});
};
const whatever4 = async () => {
return Promise.resolve(4);
};
const whatever5 = async () => {
return await Promise.resolve(4);
};
const whatever6 = async () => Promise.resolve(4);
const whatever7 = async () => await Promise.resolve(4);
在你的 IDE 中,你將能看到所有這些函數的推斷類型是 () => Promise<number>。
