【TypeScript】配列とタプルの型の書き方

JavaScript

こんにちは、かつコーチです。

前回はstringnumberbooleanという基本の型注釈を解説しました。

今回は、複数の値をまとめて扱う「配列」の型の書き方と、配列に似ているけれど少し特殊な「タプル」という型を紹介します。

配列の型の書き方

基本の書き方:型名 + []

配列の型は、要素の型の後ろに[]を付けて表します。

let names: string[] = ["かつコーチ", "たなか", "すずき"];
let scores: number[] = [80, 95, 60];
let flags: boolean[] = [true, false, true];

string[]は「文字列だけが入る配列」、number[]は「数値だけが入る配列」という意味です。

ジェネリクス形式の書き方

配列の型には、もう1つArray<型名>という書き方もあります。

let names: Array<string> = ["かつコーチ", "たなか"];
let scores: Array<number> = [80, 95];

string[]Array<string>は意味としては同じもので、どちらを使ってもかまいません。

現場ではstring[]のようなシンプルな書き方の方がよく使われる印象があるので、迷ったらこちらを基本にしておけば問題ありません。

型に合わない値を入れようとすると

let scores: number[] = [80, 95, 60];

scores.push(100); // OK:number型なので追加できる
scores.push("満点"); // エラー: Argument of type 'string' is not assignable to parameter of type 'number'.

pushで要素を追加するときも、型チェックはしっかり働きます。

配列の中に、うっかり型の違う値を紛れ込ませてしまう事故を防いでくれます。

複数の型を許容する配列

ユニオン型を組み合わせる

「文字列と数値、どちらも入る可能性がある配列」を扱いたい場合は、|(ユニオン型)を組み合わせます。

let mixedList: (string | number)[] = ["かつコーチ", 35, "たなか", 28];

(string | number)[]は「文字列または数値が入る配列」という意味です。

括弧を忘れてstring | number[]と書いてしまうと、「文字列、または数値の配列」という別の意味になってしまうので注意しましょう。

タプル型:要素数と順序が決まった配列

配列との違い

TypeScriptには、配列と似ているけれど少し特殊なタプルという型があります。

タプルは「要素数が決まっていて、それぞれの位置ごとに型も決まっている配列」です。

let userInfo: [string, number] = ["かつコーチ", 35];

[string, number]は「1番目は必ず文字列、2番目は必ず数値」という意味です。

普通の配列は「同じ型の値が何個でも入る」ものですが、タプルは「決まった数・決まった順番の値を1セットとして扱う」ためのものだとイメージすると分かりやすいです。

タプルの活用例

タプルは、意味の異なる値を1つのペアとして扱いたいときに便利です。

// [ユーザー名, 年齢] というペアの配列
const users: [string, number][] = [
  ["かつコーチ", 35],
  ["たなか", 28],
  ["すずき", 42],
];

for (const [name, age] of users) {
  console.log(`${name}さんは${age}歳です`);
}
// かつコーチさんは35歳です
// たなかさんは28歳です
// すずきさんは42歳です

[string, number][]のように書くと、「[文字列, 数値]というタプルの配列」を表せます。

順序や個数が違うとエラーになる

タプルは、順序や個数が定義と異なるとエラーになります。

let userInfo: [string, number];

userInfo = [35, "かつコーチ"]; // エラー:順番が逆
userInfo = ["かつコーチ", 35, true]; // エラー:要素数が多い
userInfo = ["かつコーチ", 35]; // OK

「1番目は文字列、2番目は数値」という約束を破ると、その場でエラーとして教えてくれます。

かつコーチが実際につまずいたポイント:配列とタプルの使い分け

何でも配列で済ませようとして読みにくくなった話

私がタプルをまだ知らなかった頃、「名前と年齢のペア」のようなデータも、とりあえずstring[]any[]のような普通の配列で済ませてしまっていました。

❌ Before:普通の配列で済ませてしまう

function createUserRow(data: any[]): string {
  // data[0] が名前、data[1] が年齢のつもりだが…
  return `${data[0]}さんは${data[1]}歳です`;
}

createUserRow(["かつコーチ", 35]); // 意図通り動く
createUserRow([35, "かつコーチ"]); // 順番を間違えても型エラーにならない

any[]にしてしまうと、配列の中身が何番目にどんな型で入っているかをTypeScriptがまったくチェックしてくれません。

引数の順番を間違えて渡しても、コンパイルの段階ではエラーにならず、実行してから「表示がおかしい」と気づくパターンを何度も経験しました。

✅ After:タプルで順序と型を固定する

function createUserRow(data: [string, number]): string {
  return `${data[0]}さんは${data[1]}歳です`;
}

createUserRow(["かつコーチ", 35]); // OK
createUserRow([35, "かつコーチ"]); // エラー:1番目はstring型である必要がある

[string, number]とタプルで定義しておけば、「1番目は名前(文字列)、2番目は年齢(数値)」という約束がコードに固定され、順番を間違えた時点でエラーとして気づけます。

この経験から、私は「同じ型の値がいくつも並ぶだけなら配列」「意味の異なる値が決まった順番で組になるならタプル」と使い分けるようにしています。

迷ったときは、この基準に立ち返ると判断しやすいはずです。

まとめ

この記事のポイント

  • 配列の型は型名[](またはArray<型名>)で表す
  • 複数の型を許容する配列は(型A | 型B)[]のようにユニオン型と組み合わせる
  • タプルは要素数と順序が固定された配列で、[型A, 型B]のように書く
  • 意味の異なる値を1セットで扱いたいときは、配列よりタプルの方が安全にミスを防げる
  • any[]で済ませてしまうと、順序や型のチェックが効かなくなるので避ける

次に読むべき記事

配列とタプルの型が扱えるようになったら、次はより複雑なデータ構造である「オブジェクトの型を定義する方法」を見ていきましょう。

→ 次の記事:オブジェクトの型を定義する方法

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