残余引数との組合せ
タプルは、残余引数、すなわち、引数に...演算子を利用したものと組み合わせることができます。そのパターンをいくつか紹介していきます。
残余引数とタプルとの組合せ
例えば、ここまで利用してきたPersonalDataタプルを引数の型とする関数show()を考えます。その引数に...演算子を適用するとします。例えば、リスト6の(1)のようなコードです。
type PersonalData = [string, number, number, Date?];
function show(...personalData: PersonalData): void { // (1)
:
}
show("田中太郎", 170.2, 74.8, new Date("2000-05-10")); // (2)
show("鈴木二郎", 170.2, 74.8); // (3)
この場合、関数show()の引数は、可変長引数となるのではなく、タプルに定義された個数とデータ型の引数となります。すなわち、リスト6の(1)の関数show()は、リスト7の関数定義と同義になります。この仕組みは、バージョン3.0で導入されました。
function show(personalData_0: string, personalData_1: number, personalData_2: number, personalData_3?: Date | undefined): void
実際、エディタ(VS Code)上でリスト6の(2)のshow()の上にキャレットを合わせると、図2のように表示され、まさにリスト7の関数定義として扱われているのがわかります。
そのため、この関数show()を利用する場合は、リスト6の(2)のように、それぞれのデータ型に合わせて引数を渡す必要があります。もし、これを次のように余分な引数を渡したり、引数が不足していたりすると、エラーとなるので注意してください。
show("田中太郎", 170.2);
show("田中太郎", 170.2, 74.8, new Date("2000-05-10"), 78);
もちろん、タプルのオプション要素については、引数に展開されてもオプションとなるので、リスト6の(3)のように、省略してもエラーにはなりません。
関数内での引数の扱い
show()関数を呼び出す際に、それぞれバラバラの引数としてわたす必要があるとしても、関数内では、引数データはタプルとしてまとめられることには注意しておいてください。ということは、第1引数として渡された名前を利用する場合は、personalData[0]としてアクセスする必要があります。これを、リスト7の定義のように、personalData_0としてアクセスすると、エラーとなるので注意してください。リスト7のように展開された関数定義は、あくまで便宜上見やすくしたものであり、引数名は仮のものとして実際には利用できない、と思っておいてください。
残余引数とラベル付きタプルとの組合せ
たとえ便宜上だとしても、仮の引数名が_0のようなものはわかりにくいものです。これが、ラベル付きタプルを利用すると、よりわかりやすい関数定義となります。例えば、リスト8のようなコードです。
type PersonalData = [name: string, height: number, weight: number, birth?: Date]; // (1)
function show(...personalData: PersonalData): void { // (2)
:
}
show("田中太郎", 170.2, 74.8, new Date("2000-05-10")); // (3)
リスト8の(1)のPersonalDataはラベル付きタプルとなっています。そして、そのPersonalDataを型指定した残余引数の関数show()を(2)で定義し、(3)でそのshow()を実行しています。この(2)と(3)のコードは、リスト6と同じです。
この(3)のshow()に対して、エディタ(VS Code)上でキャレットを合わせると、図3のように表示されます。リスト6の関数定義とは違い、引数名がタプルのラベルになっているのがわかります。
ただし、この表示もあくまで便宜上のものなのは変わりません。show()関数内で、例えば、変数heightにアクセスしようとすると、変数が存在しないためエラーとなるのは、ラベルのないタプルと同様です。
ラベル付きタプルのユニオン型と残余引数の組合せ
このラベル付きタプルのユニオン型と残余引数を組み合わせると、便利なことが可能となります。例えば、リスト9のようなコードを考えます。
type PersonalData = [name: string, height: number, weight: number] | [name: string, birth: Date]; // (1)
function show(...personalData: PersonalData): void { // (2)
:
}
リスト9の(1)のPersonalDataは、ラベル付きタプルのユニオン型となっています。共通するのは第1要素だけです。そして、このPersonalDataをデータ型とする残余引数の関数show()が、(2)で定義されています。この状態で、エディタ(VS Code)上でshow(まで入力すると、図4と図5の2種の引数候補が表示されます。これは、まさに、関数のオーバーロードと同じような状態となっています。
なお、このユニオン型タプルと残余引数を組み合わせ、オーバーロードのような働きをさせる場合、必ずしもラベル付きタプルである必要はありません。ただ、図4や図5のように候補として表示させることを前提とするならば、その引数名が明らかにわかるラベル付きタプルの利用が必須です。
