Awaited<Type> を使って Promise の返り型を定義する

TypeScript のユーティリティ型に Awaited があります。実際に導入されたのは TypeScript 4.5 からで、2021年辺りにリリースされたみたいです。

内容としては、Promise に対して、T の型定義を利用したい場合に使います。Primise はネストしていても取得できて、T には Promise 以外の型 (ここでは boolean) であっても問題ありません。

// A = string
type A = Awaited<Promise<string>>;

// B = number
type B = Awaited<Promise<Promise<number>>>;

// C = boolean | number
type C = Awaited<boolean | Promise<number>>;

また、同じくユーティリティ型の ReturnType を組み合わせると、関数の返り値の Promise の型を定義できます。以下で見ていきましょう。

個人的利用シーン

私が利用したケースとして、このブログでも使っている microcms-js-sdkgetList 関数の返り値の型を定義したかったときです。

getList は T に型を渡すと、Promise の MicroCMSListResponse T として返してくれます。

getList: <T = any>({ endpoint, queries, customRequestInit, }: GetListRequest) => Promise<MicroCMSListResponse<T>>

MicroCMSListResponse はこのような型定義になっています。getList で渡した T が、contents: (T & MicroCMSListContent)[] の定義になります。

interface MicroCMSListResponse<T> {
    contents: (T & MicroCMSListContent)[];
    totalCount: number;
    limit: number;
    offset: number;
}

上記でも述べましたが、AwaitedReturnTypeを使うと MicroCMSListResponse の定義を取得することができます。以下一例です。

export const getPosts = async () => {
  return await client.getList<PostType>({
   endpoint: "posts",
  });
};

// type PostsReturnType = MicroCMSListResponse<PostType>
type PostsReturnType = Awaited<ReturnType<typeof getPosts>>

MicroCMSListReponse の型の詳細を取得したい場合は以下になります。

// MicroCMSListResponse から contents の型定義を定義
// type PostsContenstReturnType = (PostType & MicroCMSContentId & MicroCMSDate)[]
type PostsContenstReturnType = Awaited<ReturnType<typeof getPosts>>['contents']

さらに contents のオブジェクトの型定義を取り出す方法です。

配列型(例えばPostType[])からその要素であるオブジェクトの型(PostType)を取り出すには、次のように inferIndexed Access Typesを利用します。

type ArrayElementType<T> = T extends (infer U)[] ? U : T;

// infer の利用
type PostObjectType = ArrayElementType<MicroCMSListResponse<PostType>['contents']>;

// Indexed Access Types
type PostObjectTypeAlt = MicroCMSListResponse<PostType>['contents'][number];

型定義の詳細はざっくりこのブログのリポジトリから確認することができます。ぜひ参考になればと思います。