TypeScript | 基礎文法:関数の基礎 – 戻り値型

TypeScript
スポンサーリンク

戻り値型って何を約束しているのか

関数の「戻り値型」は、「この関数は、呼び出されたときに“最終的にどんな型の値を返すか”の約束を書く場所です。

function greet(name: string): string {
  return `Hello, ${name}`;
}
TypeScript

この ): string の部分が「戻り値型」です。
ここでは「greet は必ず string を返す関数ですよ」と宣言しています。
もし number を返そうとすると、TypeScript がコンパイル時に止めてくれます。

function greet(name: string): string {
  return 123; // エラー: Type 'number' is not assignable to type 'string'.
}
TypeScript

「この関数を呼んだら、何が返ってくるのか?」を型で固定する——これが戻り値型の役割です。


基本の書き方と「型推論」との付き合い方

明示的に戻り値型を書くパターン

一番素直な書き方はこれです。

function add(a: number, b: number): number {
  return a + b;
}
TypeScript

): number が戻り値型。
このおかげで、add を使う側は「add を呼べば number が返ってくる」と安心して扱えます。

const result = add(1, 2);
// result は number と推論される
TypeScript

書かなくても動く「型推論」

TypeScript は、戻り値型を省略しても、ある程度は自動で推論してくれます。

function add(a: number, b: number) {
  return a + b;
}
// 戻り値型は number と推論される
TypeScript

ただし、実務では次のような場合はあえて明示的に書いた方がいいとよく言われます。

  • ライブラリや外部公開用の関数
  • 戻り値が複雑(ユニオン型・ジェネリクスなど)
  • 「この関数は絶対にこの型を返す」と強く保証したいとき

「自分だけが使う小さな関数」は推論に任せてもいいですが、
「他人が使う入り口」になる関数は、戻り値型をちゃんと書いておく——この感覚を持っておくと設計が安定します。


戻り値がない関数と void 型

「何も返さない」ことを表す void

ログを出すだけの関数など、「値を返さない」関数もあります。

function logMessage(message: string): void {
  console.log(message);
}
TypeScript

ここでの void は、「呼び出し側が使える“意味のある値”は返さない」という約束です。
return 自体は書けますが、値を返すことはできません。

function logMessage(message: string): void {
  console.log(message);
  return;      // OK
  // return 1; // エラー
}
TypeScript

「戻り値を使う前提がない関数」には void を付けると、読み手にも意図が伝わりやすくなります。


オブジェクトや配列を戻り値にする

オブジェクトを返す関数

type User = {
  id: number;
  name: string;
};

function createUser(id: number, name: string): User {
  return { id, name };
}
TypeScript

ここでは、「createUserUser 型のオブジェクトを返す」と宣言しています。
もしプロパティが足りなかったり、型が違ったりすると、戻り値のところでエラーになります。

function createUser(id: number, name: string): User {
  return { id }; // エラー: Property 'name' is missing in type ...
}
TypeScript

「戻り値型に“理想の形”を書いておく → 実装がそれに従っているかを TypeScript がチェックしてくれる」
という構図を意識すると、戻り値型のありがたみが見えてきます。

配列を返す関数

type Product = {
  name: string;
  price: number;
};

function getProducts(): Product[] {
  return [
    { name: "Apple", price: 100 },
    { name: "Banana", price: 80 },
  ];
}
TypeScript

Product[] は「Product の配列」。
戻り値型に配列を使うときも、「中身の型」まできっちりチェックされます。


戻り値型を「あとから再利用する」テクニック

ReturnType で「関数の戻り値型だけ」を取り出す

TypeScript には ReturnType<T> というユーティリティ型があり、
「関数型 T の戻り値の型だけを取り出す」ことができます。

function getUser() {
  return { id: 1, name: "Alice" };
}

type User = ReturnType<typeof getUser>;
TypeScript

このとき User は、次のような型になります。

type User = {
  id: number;
  name: string;
};
TypeScript

ポイントは、

  • typeof getUser で「getUser の関数型」を取り出し
  • ReturnType<...> で「その戻り値型だけ」を抜き出している

という流れです。

実務では、

  • 「実装を先に書いて、その戻り値型を型として再利用したい」
  • 「関数の戻り値の形が変わったら、関連する型も自動で追従してほしい」

といった場面でよく使われます。


戻り値型を意識するときの「設計の視点」

戻り値型は、単なる「おまけ情報」ではなく、その関数の“約束”そのものです。

関数を書くとき、こう自分に問いかけてみてください。

この関数を呼んだ人は、何を受け取れるべきか?
その値は、どんな形・どんな型をしているべきか?
その約束は、将来変わりやすいものか、それとも変えたくないものか?

その答えを、): 型 のところに正直に書いていく。
そうすると、TypeScript はこうして守ってくれます。

  • 間違った型の値を返そうとしたらコンパイルエラー
  • 実装を変えたときに、戻り値の形が変わっていないかをチェック
  • ReturnType などで、戻り値型を安全に再利用できる

「この関数は、何を返す“契約”なのか」
その契約書を書く場所が、戻り値型です。
そこを意識して書き始めると、関数の設計そのものが一段レベルアップします。

タイトルとURLをコピーしました