TypeScript | 基礎文法:関数の基礎 – デフォルト引数

TypeScript
スポンサーリンク

デフォルト引数は「来なかったときの標準値」

デフォルト引数は、「この引数が渡されなかったときは、代わりにこれを使ってね」という“標準値”をあらかじめ決めておく仕組みです。

書き方はシンプルで、引数に = で値をつけます。

function greet(name: string, title: string = "Mr.") {
  console.log(`${title} ${name}`);
}

greet("Taro");          // "Mr. Taro"
greet("Taro", "Dr.");   // "Dr. Taro"
TypeScript

ここでは、第二引数 title"Mr." というデフォルト値が設定されています。
呼び出し側が title を省略したとき、関数の中では title は自動的に "Mr." になります。

ポイントは、「呼び出し側は省略できるけど、関数の中では必ず string として扱える」ことです。
これはオプション引数(title?: string)との大きな違いです。


デフォルト引数とオプション引数の違い

オプション引数は「ないかもしれない」、デフォルト引数は「必ずある」

まずオプション引数の例から。

function greetOptional(name: string, title?: string) {
  console.log(`${title} ${name}`); // エラーの可能性
}
TypeScript

title?: string だと、「title は string かもしれないし、undefined かもしれない」という意味になります。
そのため、何もチェックせずに title を使おうとするとエラーになります。

function greetOptional(name: string, title?: string) {
  if (title) {
    console.log(`${title} ${name}`);
  } else {
    console.log(name);
  }
}
TypeScript

一方、デフォルト引数はこうです。

function greetDefault(name: string, title: string = "Mr.") {
  console.log(`${title} ${name}`); // ここでは title は常に string
}
TypeScript

ここでは、title の型は 純粋に string です。
undefined にはなりません。必ず何かしらの文字列が入っています(渡されなければ "Mr.")。

整理すると、イメージはこうです。

オプション引数(title?: string
→ 「渡されないかもしれない。中身は string | undefined

デフォルト引数(title: string = "Mr."
→ 「呼び出し側は省略できるが、中では必ず string」

「中で毎回 undefined チェックしたくない」「必ず値がある前提で書きたい」
そんなときに、デフォルト引数が威力を発揮します。


デフォルト引数が呼ばれるタイミング

「引数が省略されたとき」「undefined が渡されたとき」

デフォルト引数は、「何も渡されなかったとき」だけではなく、「undefined が渡されたとき」にも使われます

function sample(value: number = 10) {
  console.log(value);
}

sample();           // 10(省略 → デフォルト)
sample(5);          // 5
sample(undefined);  // 10(undefined → デフォルト適用)
sample(0);          // 0
TypeScript

ここでのポイントは、

sample() → 引数なし → デフォルトの 10
sample(undefined) → 明示的に undefined → それでもデフォルトの 10
sample(0) → 値あり → 0 をそのまま使う

という挙動です。

つまり、undefined は“値がない”として扱われ、デフォルト値に置き換わる」と覚えておくとよいです。
null を渡した場合はデフォルトは使われず、value はそのまま null になります。


デフォルト引数と型推論

デフォルト値から型が推論される

デフォルト値を指定すると、TypeScript はそこから引数の型を推論してくれます。

function mul(value = 1) {
  return value * 2;
}
TypeScript

この場合、value の型は自動的に number と推論されます。
戻り値も number になります。

もちろん、明示的に型を書くこともできます。

function mul(value: number = 1): number {
  return value * 2;
}
TypeScript

学習中や小さなスクリプトでは型推論に任せてもいいですが、
実務や共有コードでは、「引数型や戻り値型は積極的に明示した方が読みやすい」ことが多いです。


デフォルト引数の位置と順番

デフォルト引数は「後ろ側」に置く

オプション引数と同じく、デフォルト引数も基本は後ろ側に置くのが素直です。

function greet(name: string, title: string = "Mr.") {
  console.log(`${title} ${name}`);
}
TypeScript

実は、これは技術的には「前にデフォルト引数を置く」こともできますが、
呼び出し側が混乱しやすくなるので、実務では「必須 → デフォルト付き」の順番にするのが圧倒的に多いです。

// あまりやらない方がいい例
function weird(title: string = "Mr.", name: string) {
  console.log(`${title} ${name}`);
}
TypeScript

こうすると、呼び出し時に必ず name は渡さないといけないのに、
第一引数に「title なのか name なのか」が分かりづらくなります。

実務での感覚としては、

「前のほうは必須引数」
「後ろのほうがオプション・デフォルト付き引数」

と覚えておくと、読み手にやさしい関数になります。


デフォルト引数とオブジェクト引数の組み合わせ

設定オブジェクトにデフォルトを入れる

少し実務寄りの典型パターンです。
「オプションが増えてきたらオブジェクトにまとめる」+「そのオブジェクト自体にデフォルトを入れる」パターン。

type GreetOptions = {
  title?: string;
  upperCase?: boolean;
};

function greet(name: string, options: GreetOptions = {}) {
  const title = options.title ?? "Mr.";
  const formattedName = options.upperCase ? name.toUpperCase() : name;

  console.log(`${title} ${formattedName}`);
}

greet("Taro"); 
greet("Taro", { title: "Dr." });
greet("Taro", { upperCase: true });
greet("Taro", { title: "Prof.", upperCase: true });
TypeScript

ここでは、

第二引数 options 自体に {} というデフォルト値を設定
options を省略して呼んでも、関数内では必ずオブジェクトとして扱える

という状態になっています。

さらに、options.title ?? "Mr." で、
「title が undefined または存在しないときにだけ "Mr." を使う」というロジックを実現しています。

このパターンは実務でかなりよく出てきます。
「引数が多くなってきたら、オブジェクト + デフォルト引数」がとても読みやすい設計になります。


デフォルト引数を設計するときに考えてほしいこと

デフォルト引数は、ただの「便利機能」ではなく、設計の意思表示です。

この引数が省略されたとき、どんな振る舞いが「自然」か?
その省略時の振る舞いは、アプリ全体を通して一貫しているか?
そのデフォルト値は、時間が経っても変えたくならないか?

例えば、

function fetchUsers(limit: number = 20) {
  // limit件だけユーザーを取ってくる
}
TypeScript

ここでの 20 は、「このアプリでは、ユーザー一覧のデフォルト表示件数は 20」という仕様そのものです。
もしあとから「やっぱ 50 件にしよ」となると、ここを書き換えることになります。

だからこそ、デフォルト引数を書くときは、
「これはこの仕様の“標準設定”なんだ」と自覚して決めるのが大事です。


まとめ:デフォルト引数の本質的な役割

デフォルト引数は、ざっくり言えばこういうものです。

「この引数が来なかったときは、アプリとして“これを標準値とみなす”」
「呼び出し側には引数を省略する自由を与えつつ、関数の中では“必ず値がある世界”を作る」

その結果として、

呼び出し側のコードがスッキリし
関数の中では undefined チェックが減り
仕様上の“標準の振る舞い”が、コードにそのまま刻まれる

という状態が作れます。

オプション引数とセットで、こんな質問を自分に投げかけてみてください。

「この引数がないとき、“何もしない”のが自然なのか?」
「それとも、“この値が使われる”のが自然なのか?」

前者ならオプション引数(?)、
後者ならデフォルト引数(=)です。

その選び方そのものが、あなたの設計センスになっていきます。

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