Awaited<T>
最終更新:2026-10-22
Awaited<T> Awaited
Awaited<T> は await の型レベルの効果を模倣します。Promise<T> を解いて T を得て、ネストした Promise(Promise<Promise<T>>)も再帰的に展開します。「async 関数が成功した後の結果の型」が欲しいとき、Awaited<ReturnType<typeof fn>> が標準的な組み合わせです。
| グループ | ユーティリティ型 |
|---|---|
| 種類 | 型 |
| strict モード | 不要 |
ℹ️ 説明 エディタは TypeScript を JavaScript にトランスパイルして実行します(型チェックなし)。型チェック結果は各サンプルの出力を参照してください。
📝 構文
// 簡略化した実装(公式版は thenable も処理する)
type Awaited<T> = T extends Promise<infer V> ? Awaited<V> : T;
// 使い方
type User = Awaited<ReturnType<typeof fetchUser>>; // Promise<User> を解く
⚙️ パラメータ
| T | 任意の型です。Promise(または thenable)なら再帰的に解き、そうでなければそのまま保たれます |
|---|
戻り値:T が await された後の型です。Promise の連鎖がすべて展開された最終的な値の型です。
▶ サンプル
下のコードを編集して「試す」を押すと、トランスパイル実行結果を確認できます:
出力:
1: Ada
done
(トランスパイル後の実行出力。型レベルでは LoadedUser は { id: number; name: string } であり Promise<...> ではありません。Awaited が解いているため、user.id に直接アクセスできます)
💡 ポイント
ℹ️ 説明 Awaited は再帰的な条件型です。Promise に遭遇すると infer で内部の型を取り出し、それに対して再び Awaited を適用し、Promise でなくなるまで続けます。これは TS が内部で await 式の型を導出するのと同じ仕組みです。
⚠️ 注意 Awaited は型レベルで「解く」だけで、あなたの代わりに待ってはくれません。実行時に await を忘れたら手元に残るのは依然として Promise オブジェクトです。型が正しく書けても、await を書いたことにはなりません。
💡 ヒント 組み合わせの技として、Awaited<ReturnType<typeof fn>> で async 関数の成功結果を取れます。Promise.all の結果の型の中でも、各メンバーはそれぞれ Awaited で展開されています。
🏷️ 関連ユーティリティ型
💡 関連ケース
ケースは今後追加予定です。
📚 関連チュートリアル
❓ よくある質問
Q Awaited<T> と自作の T extends Promise<infer U> の違いは何ですか?
A 再帰しない自作の条件型は1層しか解けず、ネストした Promise<Promise<T>> を取りこぼします。公式の Awaited は再帰的に展開し、thenable(独自の then メソッドを持つオブジェクト)にも対応します。汎用に使うなら Awaited を選びましょう。
Q 普通の値に await を付けると何が起こりますか?
A 実行時には await しても Promise でない値はそのまま返ります。型の上でも Awaited<string> は string です。だから「Promise かもしれない値」の型の導出に Awaited を使うのは常に安全です。
Q Promise.all の結果の型はどう取りますか?
A 手で書く必要はありません。Promise.all がタプルを受け取ると、戻り値の型は自動的に各メンバーを Awaited で展開したタプルになります。この型を参照したいなら const results = await Promise.all([...]) と宣言してから typeof results を使いましょう。