メインコンテンツまでスキップ

オプション引数 (optional parameter)

オプション引数(optional parameter)は、渡す引数を省略できるようにするTypeScript固有の機能です。オプション引数は疑問符?を引数名の後ろに書くことで表現します。

オプション引数の構文

ts
function 関数名(引数名?: ) {}
// ^オプション引数の標示
ts
function 関数名(引数名?: ) {}
// ^オプション引数の標示

オプション引数は、関数を呼び出すときに引数が省略できます。

ts
function hello(person?: string) {}
hello(); // 引数を省略して呼び出せる
hello("alice"); // 省略しない呼び出しももちろんOK
ts
function hello(person?: string) {}
hello(); // 引数を省略して呼び出せる
hello("alice"); // 省略しない呼び出しももちろんOK

省略するとundefinedになる

オプション引数の型は、型とundefinedユニオン型になります。ユニオン型は日本語で言うと「いずれか」の意味です。上の例では、引数personstring | undefined型になります。

ts
function hello(person?: string) {}
(parameter) person: string | undefined
ts
function hello(person?: string) {}
(parameter) person: string | undefined

引数を省略した場合、オプション引数の実行時の値はundefinedになります。

ts
function hello(person?: string) {
console.log(person);
}
hello();
undefined
ts
function hello(person?: string) {
console.log(person);
}
hello();
undefined

オプション引数の取り回し

オプション引数は、型がundefinedとのユニオン型になるため、そのままでは使えません。たとえば、次のコードはstringのtoUpperCaseメソッドを呼び出すコードです。これはコンパイルエラーになります。なぜなら、personundefined型である可能性があるからです。そして、undefinedにはtoUpperCaseメソッドがありません。

ts
function hello(person?: string) {
return "Hello " + person.toUpperCase();
Object is possibly 'undefined'.2532Object is possibly 'undefined'.
}
ts
function hello(person?: string) {
return "Hello " + person.toUpperCase();
Object is possibly 'undefined'.2532Object is possibly 'undefined'.
}

この問題を解消するには、次の2つの方法があります。

デフォルト値を代入する

引数がundefinedの場合分けをif文で書き、そこでデフォルト値を代入する方法です。

ts
function hello(person?: string) {
if (typeof person === "undefined") {
person = "anonymous";
}
return "Hello " + person.toUpperCase();
}
ts
function hello(person?: string) {
if (typeof person === "undefined") {
person = "anonymous";
}
return "Hello " + person.toUpperCase();
}

Null合体代入演算子??=でデフォルト値を代入する方法もあります。

ts
function hello(person?: string) {
person ??= "anonymous";
return "Hello " + person.toUpperCase();
}
ts
function hello(person?: string) {
person ??= "anonymous";
return "Hello " + person.toUpperCase();
}

さらに、デフォルト引数を指定することでも同じことができます。多くのケースでは、デフォルト引数を使うほうがよいです。

ts
function hello(person: string = "anonymous") {
// ^^^^^^^^^^^^^デフォルト引数
return "Hello " + person.toUpperCase();
}
ts
function hello(person: string = "anonymous") {
// ^^^^^^^^^^^^^デフォルト引数
return "Hello " + person.toUpperCase();
}

📄️ デフォルト引数

引数の値がundefinedのとき、代わりの値を指定できるのがデフォルト引数(default parameter)です。

処理を分ける

オプション引数を取り回すもうひとつの方法は、処理を分けることです。

ts
function hello(person?: string) {
if (typeof person === "undefined") {
return "Hello ANONYMOUS";
}
return "Hello " + person.toUpperCase();
}
ts
function hello(person?: string) {
if (typeof person === "undefined") {
return "Hello ANONYMOUS";
}
return "Hello " + person.toUpperCase();
}

T | undefinedとの違い

オプション引数はユニオン型T | undefinedとして解釈されます。であれば、引数の型をT | undefinedと書けば同じなはずです。なぜTypeScriptは、疑問符?という別の記法を用意したのでしょうか。違いがあるのでしょうか。

これには呼び出す側で、引数を省略できるかどうかという違いが生まれます。オプション引数は引数自体を省略できますが、T | undefined型の引数は引数が省略できません。

たとえば、次のオプション引数の関数は引数なしで呼び出せます。

ts
function hello(person?: string) {}
hello(); // 引数を省略して呼び出せる
ts
function hello(person?: string) {}
hello(); // 引数を省略して呼び出せる

一方、次のようなundefinedとのユニオン型の引数は、引数なしではコンパイルエラーになります。

ts
function hello(person: string | undefined) {}
hello();
Expected 1 arguments, but got 0.2554Expected 1 arguments, but got 0.
ts
function hello(person: string | undefined) {}
hello();
Expected 1 arguments, but got 0.2554Expected 1 arguments, but got 0.

この関数を呼び出すためには、undefinedを渡す必要があります。

ts
function hello(person: string | undefined) {}
hello(undefined);
ts
function hello(person: string | undefined) {}
hello(undefined);

オプション引数の後に普通の引数は書けない

オプション引数は必ず最後に書かなければいけません。次のようにオプション引数より後ろに普通の引数を書くと、コンパイルエラーになります。

ts
function func(foo?: string, bar: string) {}
A required parameter cannot follow an optional parameter.1016A required parameter cannot follow an optional parameter.
ts
function func(foo?: string, bar: string) {}
A required parameter cannot follow an optional parameter.1016A required parameter cannot follow an optional parameter.