Last updated at
型A = Promise<B>
である際にA
からB
を導き出したい。
type A = Promise<B>
type C = /* AからBを取り出したい */
infer
を使う。
type PromiseType<T extends Promise<any>> = T extends Promise<infer P>
? P
: never
type A = Promise<B>
type C = PromiseType<A> // B
型名の直後のextends Promise...
はなくても動くが、使う際にわかりやすくなるため個人的には書くことを推奨。
ちなみにutility-typesというパッケージがこの型を公開しているので、ユーティリティ型を多用する場合はそちらを使ったほうがよい。
また、Bluebird のような似非 Promise を(or も)使いたい場合はPromiseLike
を使うとよい。
type PromiseType<T extends PromiseLike<any>> = T extends PromiseLike<infer P>
? P
: never
type A = PromiseType<Promise<number>> // number
import * as Bluebird from 'bluebird'
type B = PromiseType<Bluebird<string>> // string
このinfer
を使った型パラメータの抽出は書き方を覚えておくと、さくっと書けて結構便利。
interface Box<T> {
value: T
}
type BoxType<T extends Box<any>> = T extends Box<infer P> ? P : never
type A = Box<number>
type B = BoxType<A> // number
基本的には外部のライブラリを使う際、特にPromise
を返す関数の結果の型を使いたい場合に役立つ。
// a.ts
export const someApi = () => Promise.resolve(0)
// b.ts
import { someApi } from 'a.ts'
type ResponseOfApi = PromiseType<ReturnType<typeof someApi>>
function mutateApiResponse(res: ResponseOfApi) {
/* ... */
}
mutateApiResponse(await someApi())