TypeScript.ReturnType
その名の通り返り値の型を抜き出してくれる。
code:ts
type T0 = ReturnType<() => string>; // string
type T1 = ReturnType<(s: string) => void>; // void
ReturnTypeに関する この記事 を読んでいくよ。 code:ts
function getInt(a: string) {
return parseInt(a);
}
type A = ReturnType<typeof getInt>; // => number
まず、大前提としてReturnTypeの型引数に入れるのは当然「型」でないといけない。
そのために typeof で関数の型を取得してReturnTypeに渡している。
この利用法の利点は、型定義と利用側で型が分裂しないことである。
ReturnType の実装
code:ts
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
ReturnTypeは infer で型推定を行っているに過ぎない。
なので以下のような例だとうまく推定されない。
code:ts
const None = "None";
function none() {
return {type: None}
}
type NoneType = ReturnType<typeof none>; // => {type: string}
ここでは本当は {type: string} になってほしい。そうするにはexplicitに型宣言しておく必要がある。
code:ts
function none() {
return {type: None as typeof None}
}
type NoneType = ReturnType<typeof none>; // => {type: "None"}
型引数を渡す
実はできない。
code:ts
function identity<T>(a: T) : T {
return a;
}
type IdentityType = ReturnType<typeof identity>; // => {}
type IdentityType = ReturnType<typeof identity<number>>; // => syntax error!
本当は number を出して欲しいところなのだが・・・
原因は typeof foo で型変数が使えないのが問題のようだ。
そのため外から型引数を渡せるような Callable 型を作ってGenericReturnTypeを作ってやればいいらしい。
code:ts
interface Callable<R> {
(...args: any[]): R;
}
type GenericReturnType<R, X> = X extends Callable<R> ? R : never;
type N = GenericReturnType<number, typeof foo>; // number