TypeScriptの変更点まとめ、要素数と各要素のデータ型を指定した配列「タプル」を解説
ますます便利になるTypeScript! バージョン3からの変更点と総まとめ 第2回
タプルの残余要素
タプルと残余引数の組み合わせで登場した...演算子に関して、これをタプルの定義内で利用することも可能です。つまり、残余要素です。最後に、この残余要素を紹介していきます。
残余要素の基本
残余要素が定義されたタプルの例としては、リスト10のようなものがあります。
type PersonalData = [string, number, number, ...string[]]; // (1) const taro: PersonalData = ["田中太郎", 170.2, 74.8]; // (2) const jiro: PersonalData = ["鈴木二郎", 170.2, 74.8, "こんにちは"]; // (3) const saburo: PersonalData = ["山本三郎", 170.2, 74.8, "こんにちは", "さようなら", "またあした"]; // (4)
リスト10の(1)のPersonalDataの最後の要素が、「...string[]」と、文字列配列に対して...が適用されています。このように定義すると、第3要素までは定義通りのデータを記述する必要がありますが、第4要素以降に関しては、文字列を複数定義できますし、定義しなくてもかまいません。実際、リスト10の(2)の第4要素を定義していないパターン、(3)の1個のパターン、(4)の3個のパターンの全てがエラーなく実行できます。
残余要素とジェネリクスの組合せ
この残余要素に対して、ジェネリクスによる型指定が、バージョン3.0で可能となりました。例えば、リスト11のようなコードです。
function show<T>(personalData: [string, number, number, ...T[]]) { // (1)
:
}
show<string>(["田中太郎", 170.2, 74.8, "こんにちは", "さようなら", "またあした"]); // (2)
show<number>(["鈴木二郎", 170.2, 74.8, 51, 52, 53]); // (3)
リスト11の(1)の関数show()では、残余要素のデータ型をTとしており、その型をジェネリクス(<T>)で指定できるようになっています。この関数を利用する場合は、(2)や(3)のようになります。(2)ではジェネリクスとしてstringを指定しているので、引数タプルの第4要素以降は文字列となっています。一方、(3)では、numberをジェネリクスとして型指定しているので、第4要素以降は数値となっています。
残余要素を任意の要素に定義可能に
当初、この残余要素に関しては、必ずタプル定義の末尾の要素として定義する必要がありました。「残余(Rest)」という命名からは、当たり前といえば当たり前ですが、バージョン4.2で任意の要素に定義できるようになりました。例えば、リスト12のようなコードです。
type PersonalData = [string, number, ...string[], number]; // (1) const taro: PersonalData = ["田中太郎", 170.2, 74.8]; // (2) const jiro: PersonalData = ["鈴木二郎", 170.2, "こんにちは", 74.8]; // (3) const saburo: PersonalData = ["山本三郎", 170.2, "こんにちは", "さようなら", "またあした", 74.8]; // (4)
リスト12の(1)のPersonalDataでは、残余要素を第3要素として定義しています。そのため、(2)の数値と数値の間に文字列が全くない状態は当然として、(3)や(4)のように、数値と数値の間に任意の文字列を指定できるようになっています(もちろん、この定義が可読性の観点からよいかどうかは別として)。
このように任意の位置に定義できるようになった残余要素ですが、制約が2点あります。まず、残余要素は必ずひとつのタプルにひとつしか定義できないということです。そのため、次のようなコードはエラーとなります。
type PersonalData = [...string[], number, ...string[], number];
もうひとつの制約は、残余要素とオプション要素は混在できない、ということです。そのため、次のようなコードはエラーとなります。
type PersonalData = [...string[], number, string, number?];
ラベル付きタプルとラベルなしタプルの混在
このような残余要素を含むタプルに対して、もちろんラベルを付けることもできます。例えば、リスト13のような定義コードです。
type PersonalData = [name: string, height: number, weight: number, ...msgs: string[]];
ここでの注意点は、...をラベル(名称)の方につけ、型指定はstring[]のように単なる配列として定義することです。
このように定義したタプルを生成する場合、もちろん、リスト10の(2)〜(4)のように、taro、jiro、saburoは問題なく定義できます。
ところで、このような残余要素を含むタプルに対してラベルを付与しようとした場合、残余要素という性質上、ラベルがそもそもつけづらい要素の場合も出てきます。このラベル付きタプルがバージョン4.0で導入されて以来、実は、ラベルを利用する場合は全ての要素につける必要がありました。すなわち、ラベルのついている要素とついていない要素を混在させることができませんでした。そこで、名称が決めづらい残余要素の場合は、例えばrestやothersのように、当たり障りのないラベルを採用していました。
これが、バージョン5.2でラベルのある要素とラベルのない要素が混在できるようになりました。そのため、リスト13は、リスト14のような定義でも問題なく動作するようになっています。
type PersonalData = [name: string, height: number, weight: number, ...string[]];
まとめ
TypeScriptのバージョン5.2までに導入された新機能をテーマごとに紹介する本連載の第2回目はいかがでしたでしょうか。
今回は、タプルに関するアップデートを紹介しました。具体的には、読み取り専用やラベル付きタプル、さらに残余引数との組合せ、残余要素に関しての新機能を紹介しました。次回は、型にまつわる新しい仕組みを紹介します。
この記事は参考になりましたか?
既に会員の方はを行ってください。
- ますます便利になるTypeScript! バージョン3からの変更点と総まとめ連載記事一覧
- この記事の著者
-
WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)
<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
