メインコンテンツまでスキップ

Awaited<T>

Awaited<T>は、Promiseの解決値の型Tを取得するユーティリティ型です。
Promiseが解決するまでの非同期処理の結果が必要な場合や、async/awaitパターンで複数の入れ子になったPromiseの中から解決済みの値の型を取り出したい場合に非常に便利です。

Awaited<T>の型引数

T

型引数Tには、任意の型を渡します。それがPromise<V>である場合は解決された型であるVを返します。これはPromiseが何重にネストしていても、最終的な解決値の型を取得できます。

Awaitedの使用例

ts
type Awaited1 = Awaited<string>;
type Awaited1 = string
type Awaited2 = Awaited<Promise<string>>;
type Awaited2 = string
type Awaited3 = Awaited<Promise<Promise<string>>>;
type Awaited3 = string
ts
type Awaited1 = Awaited<string>;
type Awaited1 = string
type Awaited2 = Awaited<Promise<string>>;
type Awaited2 = string
type Awaited3 = Awaited<Promise<Promise<string>>>;
type Awaited3 = string

Promiseがネストしていても解決された値を取得できるのはなぜか

まずはAwaited<T>の実装を見てみましょう。

ts
type Awaited<T> = T extends null | undefined
? T
: T extends object & { then(onfulfilled: infer F, ...args: infer _): any }
? F extends (value: infer V, ...args: infer _) => any
? Awaited<V>
: never
: T;
ts
type Awaited<T> = T extends null | undefined
? T
: T extends object & { then(onfulfilled: infer F, ...args: infer _): any }
? F extends (value: infer V, ...args: infer _) => any
? Awaited<V>
: never
: T;

少々複雑ですが、ひとつずつみていきましょう。

まずTnullまたはundefinedである場合はそのままTを返します。次に、Tobjectであり、thenメソッドを持つ場合は、そのthenメソッドの第1引数の型を取得します。この型がPromiseの解決値である場合は再帰的にAwaitedを適用します。これにより、Promiseが何重にネストしていても、最終的な解決値の型を取得できるようになります。