[TypeScript]AwaitedとReturnTypeを調べたメモ
#経緯
Remixのチュートリアルを眺めていたら、Awaited<ReturnType<typeof getPosts>>
という型定義が出てきて気になったので調べた。
https://remix.run/docs/en/v1/tutorials/blog#a-little-refactoring
#Awaited型とは
TypeScript4.5から入ったAwaited型
導入されたPRは以下。
https://github.com/microsoft/TypeScript/pull/45350
この型ではネストしたPromiseを再帰的に評価した結果の型として表現できる。
※以下のコードは上記リリースノートのURLから抜粋
// A = string
type A = Awaited<Promise<string>>;
// B = number
type B = Awaited<Promise<Promise<number>>>;
// C = boolean | number
type C = Awaited<boolean | Promise<number>>;
これにより、Promise.allなどの型定義が便利になるようだ。
Promise.resolveの型はresolve<T>(value: T | PromiseLike<T>): Promise<T>
みたいな形になっており、TまたはPromiseLikeを受け取れる。
つまり、PromiseをラップしたPromiseは以下のような型になる。
type Foo = Promise<number | PromiseLike<number>>;
const foo: Foo = new Promise((r1) => r1(new Promise((r2) => r2(1))));
これを前提においた上で以下のような関数を定義を考える。
type Foo = Promise<number | PromiseLike<number>>;
async function foo(): Promise<[number]> {
const foo: Foo = new Promise((r1) => r1(new Promise((r2) => r2(1))));
return await Promise.all([foo]);
}
4.4以前だと、Promise.allにAwaitedがなかったため、await Promise.all([foo])
の型が、[number | PromiseLike<number>]
になってしまい、エラーになってしまう。
TypeScript Playgroundで試した結果(4.4.4)
一方、4.5以上だとPromise.allにAwaitedが導入されているため、Promise<[number]>
として評価され通るようになる、ということらしい。
TypeScript Playgroundで試した結果(4.5.5)
#ReturnTypeとは
以下のドキュメントが全てではあるが、関数型の返り値を取得するUtility Types。
https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype
typeof
と併用することで、関数の実体から型を抽出して使うこともできる。
https://www.typescriptlang.org/docs/handbook/2/typeof-types.html
function foo(): string {
return "foo";
}
// type Foo = string;
type Foo = ReturnType<typeof foo>;
// type Bar = string;
type Bar = ReturnType<() => string>;