mosya<TC> - 関数の戻り値を返す型、ReturnTypeを自分で実装するの解説
この記事はmosya<TC>の問題の一つであるMyReturnType型の解説になります。
問題
組み込みの型ユーティリティReturnType
例えば以下のようなコードを満たすようにMyReturnType型を実装しましょう。
const fn = (v: boolean) => {
if (v) return 1;
else return 2;
};
type a = MyReturnType<typeof fn>; // should be "1 | 2"
前提知識
この問題を解くにあたって型についての以下の知識を理解しておく必要があります。
Conditional Types
を理解するinfer
を理解する
Conditional Typesを理解する
Conditional Typesは、条件によって型を変更することができる機能です。
例えば、以下のような型が考えられます。
type Foo<T> = T extends string
? string
: number;
この型は、T
がstring
型を継承している場合はstring
型を、そうでない場合はnumber
型を返します。
このように、extends
を使って条件を指定することで、型を変更することができます。
inferを理解する
infer
は、型を推論することができる機能です。
例えば、以下のような型が考えられます。
type ArrayItem<T> =
T extends (infer R)[] ? R : never;
この型は、T
が配列の場合は、配列の中の型を返します。
以下のように使うことができます。
type Foo = ArrayItem<string[]>; // string
この場合、infer R
にはstring[]
型が当てはまるので、R
はstring
型に推論され、R
を返すのでstring
型が返されます。
このように推論される型を取得するのにinfer
は役立ちます。
解答例
以上の知識を使って、以下のように解答することができます。
type MyReturnType<T> = T extends (
...args: any[]
) => infer R
? R
: never;
関数の引数は何個あるかわからないので、...args: any[]
として可変長としています。
帰り値を推論したいので、infer R
を使ってR
に推論された型を代入しています。
条件にマッチ、すなわちT
が関数の場合は、推論したR
を返します。
Authored by
Godai@steelydylan
Webサービスを作るのが好きなWebエンジニア。子供が産まれたことをきっかけに独立し法人化。サービス開発が大好き。
好きな言語はTypeScript。