配列の型推論とは何か
TypeScriptは、わざわざ「: string[]」のように型を書かなくても、初期値から配列の型を自動で推論してくれます。
つまり、次のように書いた瞬間に、コンパイラは「これは number の配列だな」「これは string の配列だな」と理解します。
const nums = [1, 2, 3]; // number[] と推論される
const names = ["Taro", "Hanako"]; // string[] と推論される
TypeScriptここで重要なのは、「配列の中身の型を見て、配列全体の型を決めている」という感覚です。
この“中身からの推論”が、配列の型推論の基本になります。
単一の型だけが入っている配列の推論
すべて number の場合
const scores = [80, 90, 100];
// 型: number[]
TypeScript要素がすべて number なので、「number の配列」と推論されます。
この時点で、TypeScriptは次のようなチェックをしてくれます。
scores.push(120); // OK
// scores.push("120"); // エラー: string は入れられない
TypeScript「最初に入っていたもの」と「その後に入れようとしているもの」が型として一致しているかを、ずっと見てくれます。
すべて string の場合
const messages = ["hello", "bye"];
// 型: string[]
TypeScript同じく、「string の配列」と推論されます。
messages[0] = "hi"; // OK
// messages[1] = 123; // エラー
TypeScript「配列の型推論=要素の型を見て決める」というパターンが、ここでは素直に効いています。
複数の型が混ざった配列の推論(ユニオン型になる)
number と string が混ざっている場合
const mixed = [1, "2", 3];
// 型: (number | string)[]
TypeScriptTypeScriptは、「この配列には number も string も入っている」と判断し、
「number または string の配列」として推論します。
mixed.push(4); // OK
mixed.push("5"); // OK
// mixed.push(true); // エラー: boolean はダメ
TypeScriptここで大事なのは、「配列の要素型がユニオン型になる」ということです。
「(number | string)[]」という形は、実務でもよく出てきます。
boolean などがさらに混ざるとどうなるか
const values = [1, "2", true];
// 型: (number | string | boolean)[]
TypeScript単純に「出てきた型を全部足したユニオン」になります。
あまりに何でもかんでも混ぜると、型としても「何でもアリ」に近づいてしまうので、
「この配列は何を入れる場所なのか」を意識して設計した方がいいです。
空配列から始めるときの落とし穴
何も入っていないと、推論できない
const xs = [];
TypeScript中身がないので、TypeScriptは「要素の型」を推論できません。
設定によっては any[] になったり、エラーになったりします。
any[] になってしまうと、「何でも入る配列」になってしまい、型チェックがほぼ効かなくなります。
let xs = [];
xs.push(1);
xs.push("hello");
// xs は any[] になりがち
TypeScriptこれはかなり危険な状態です。
空配列から始めるなら、型を明示する
空配列スタートが必要なときは、必ず型を書いてあげるのがおすすめです。
const xs: number[] = [];
xs.push(1);
// xs.push("hello"); // エラー
TypeScript「この配列は number の配列だ」と最初に宣言しておけば、
空配列から始めても、以降の操作にちゃんと型チェックが効きます。
const と as const が絡んだときの推論
const だけの場合
const colors = ["red", "green", "blue"];
// 型: string[]
TypeScriptconst で宣言していても、配列の中身は「string の配列」として推論されます。
要素は "red" や "green" というリテラル値ですが、型としては string にまとめられます。
as const を付けた場合(タプル+リテラル型になる)
const colors = ["red", "green", "blue"] as const;
// 型: readonly ["red", "green", "blue"]
TypeScriptas const を付けると、「配列」ではなく「タプル」として推論されます。
要素の型も "red" | "green" | "blue" ではなく、それぞれ "red", "green", "blue" というリテラル型になります。
これは「配列の型推論」というより、「タプル+リテラル型推論」の話になるので、
まずは「as const を付けると、普通の配列推論とは違う世界になる」とだけ覚えておけばOKです。
初心者がまず掴んでおきたい配列の型推論の感覚
配列の型推論で本当に大事なのは、この3つです。
「要素が全部同じ型なら、その型の配列として推論される」
「複数の型が混ざっていれば、ユニオン型の配列として推論される」
「空配列は危険なので、型を明示するか、最初から要素を入れておく」
そしてもうひとつ、実務的に効いてくる感覚としては、
「この配列は何の配列なのか?」を常に言語化してから書く、ということです。
「ユーザーの配列なら User[]」
「ID の配列なら number[] か string[]」
「状態の配列なら Status[]」
その「何の配列か」という意図を、TypeScriptは初期値から推論しようとしてくれます。
推論に任せていいところと、「ここはちゃんと型を書こう」という境界線を、自分の中で少しずつ育てていくと、
配列の型推論は一気に“味方”として感じられるようになります。
