mosya
mosya Business はこちら

mosya<TC> - 関数の戻り値を返す型、ReturnTypeを自分で実装するの解説

この記事はmosya<TC>の問題の一つであるMyReturnType型の解説になります。

問題

組み込みの型ユーティリティReturnTypeを使用せず、Tの戻り値の型を取得する型を実装します。

例えば以下のようなコードを満たすようにMyReturnType型を実装しましょう。

const fn = (v: boolean) => {
  if (v) return 1;
  else return 2;
};

type a = MyReturnType<typeof fn>; // should be "1 | 2"

前提知識

この問題を解くにあたって型についての以下の知識を理解しておく必要があります。

  1. Conditional Typesを理解する
  2. inferを理解する

Conditional Typesを理解する

Conditional Typesは、条件によって型を変更することができる機能です。

例えば、以下のような型が考えられます。

type Foo<T> = T extends string
  ? string
  : number;

この型は、Tstring型を継承している場合はstring型を、そうでない場合はnumber型を返します。

このように、extendsを使って条件を指定することで、型を変更することができます。

inferを理解する

inferは、型を推論することができる機能です。

例えば、以下のような型が考えられます。

type ArrayItem<T> =
  T extends (infer R)[] ? R : never;

この型は、Tが配列の場合は、配列の中の型を返します。

以下のように使うことができます。

type Foo = ArrayItem<string[]>; // string

この場合、infer Rにはstring[]型が当てはまるので、Rstring型に推論され、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。

ReactやTypeScriptなどの周辺技術が学べる
オンライン学習サービスを作りました!

詳しくはこちら
mosya

mosyaはオンラインでHTML,CSS,JavaScriptを基本から学習できるサービスです。現役エンジニアが作成した豊富なカリキュラムに沿って学習を進めましょう。

© 2023 - mosya. All rights reserved.