ウェブエンジニア問題集

関数と型 — 引数・戻り値・オーバーロード

この章では、関数に関する型付けパターンを整理します。02章で触れた基本に加え、実務で頻出するパターンを扱います。

学習者学習者

関数の引数と戻り値、どこまで型を書けばいいんだろう?全部書くべき?それとも省略できる?


扱うトピック

オプショナル引数とデフォルト値

function greet(name: string, greeting?: string): string {
  return `${greeting ?? 'こんにちは'}、${name}さん`;
}
 
function greetWithDefault(name: string, greeting: string = 'こんにちは'): string {
  return `${greeting}、${name}さん`;
}

? を付けたオプショナル引数とデフォルト値付き引数の違い、使い分けを解説予定です。

レストパラメータ

function sum(...numbers: number[]): number {
  return numbers.reduce((a, b) => a + b, 0);
}

コールバック関数の型

type ClickHandler = (event: MouseEvent) => void;
 
function registerHandler(handler: ClickHandler): void {
  // ...
}

Reactのイベントハンドラやpropsで渡すコールバックの型付けパターンを解説予定です。

関数オーバーロード

function format(value: string): string;
function format(value: number): string;
function format(value: string | number): string {
  // 実装
}

オーバーロードの書き方と、ユニオン型で代替できるケースとの使い分けを解説予定です。

関数の型定義

// 型エイリアスで関数の型を定義
type Comparator<T> = (a: T, b: T) => number;

戻り値の型:void・never・undefined

TypeScript では returnthrow の使い方によって、関数の戻り値型が変わります。この3つの型は混同しやすいので整理します。

void — 値を返さない関数

void は「意味のある値を返さない」ことを表します。return を書かない関数、または return; だけの関数に対して TypeScript が推論する型です。

function logMessage(message: string): void {
  console.log(message);
  // return を書かない(または return; だけ)
}
 
// void な関数の戻り値を使おうとすると型エラー
const result = logMessage('hello');
result.toUpperCase(); // Error: 'result' は 'void' 型

voidundefined と似ていますが、「戻り値を使ってはいけない」という意図を型で表せる点が異なります。コールバック型によく登場します。

// イベントハンドラは「戻り値を使わない」ことを void で表す
type ClickHandler = (event: MouseEvent) => void;
 
// 戻り値が void な関数型には、実際に値を返す関数も代入できる
const handler: ClickHandler = (e) => e.target; // エラーにならない

never — 絶対に戻らない関数

never は「関数が正常に終了しない」ことを表します。throw する関数や無限ループする関数の戻り値型です。

// throw する関数の戻り値型は never
function fail(message: string): never {
  throw new Error(message);
}
 
// 無限ループも never
function infiniteLoop(): never {
  while (true) {}
}

never の実用的なメリットは、型の絞り込みに使えることです。

function assertDefined<T>(val: T | null | undefined, label: string): T {
  if (val == null) {
    fail(`${label} は必須です`); // never を返すので、以降 val は T 型に確定
  }
  return val; // ここでは val: T
}

fail()never を返すため、TypeScript はその後のコードには valnull / undefined でないと判断できます。

undefined — undefined という値を返す関数

undefined は「undefined という値そのものを返す」ことを表します。

function findUser(id: number): User | undefined {
  return users.find((u) => u.id === id); // 見つからないと undefined
}

voidundefined の違いをまとめます。

意味戻り値を変数に代入できる?
void意味のある値を返さないできる(ただし void 型になる)
undefinedundefined という値を返すできる(undefined として扱える)
never絶対に戻ってこない到達不能なので意味がない

この章の詳細な内容は順次追加していきます。