問題の発生誰しも一度は経験することです。空の配列を初期化し、単純な文字列を .push() しようとすると、TypeScript が突然赤い波線を表示します。コードは標準的な JavaScript のように見えますが、コンパイラはそれを拒否します。
const items = [];
// ❌ TypeScript エラー
items.push("new item");
// 型 'string' の引数を型 'never' のパラメーターに割り当てることはできません。
これは TypeScript が開発者の意図を推測しようとするために起こります。型や初期値なしで空の配列を宣言すると、推論エンジンはその配列が 常に 空のままであると想定します。この「ありえない」状態を表現するために、never[] 型を割り当てるのです。
根本原因:なぜ 'never' なのか?TypeScript の世界において、never はボトム型(bottom type)です。これは「存在してはならない値」を表します。const items = []; と書き、コンテキストを提供しない場合、コンパイラは安全策をとります。この配列にデータが入る可能性は 0% であると想定するのです。
never には何の型も割り当てられないため、文字列や数値を追加しようとすると型の不一致が発生します。本質的に、コンパイラが「永久に空」というラベルを貼った箱に、何かを入れようとしている状態なのです。
エラーを修正するための解決策### 1. 明示的な型アノテーション初期化時に型を割り当てるのが、最もクリーンな修正方法です。これにより、プロジェクトが成長したときに何を期待すべきかをコンパイラに正確に伝えることができます。これは、プロフェッショナルな TypeScript コードベースの 90% で行われている一般的な手法です。
// 配列が文字列を保持することを明示的に定義
const items: string[] = [];
// これは正常に動作します
items.push("new item");
複雑なデータを扱いますか?まずは interface や type を定義して、コードを整理しましょう。
interface Product {
id: string;
price: number;
}
const cart: Product[] = [];
cart.push({ id: "A101", price: 29.99 });
2. 配列のジェネリクス構文を使用するチームによっては Array<T> 構文を好む場合もあります。機能的には角括弧([])による表記と全く同じですが、複雑なネストされた型を扱う場合には読みやすくなることがあります。
const tags = new Array<string>();
tags.push("typescript"); // エラーは発生しなくなります
3. React の useState フックを修正するこのエラーは、React 開発者にとって頻繁に悩みの種となります。state フックを空の配列で初期化すると、TypeScript はデフォルトで never[] と推論します。フックにジェネリクスの型引数を提供する必要があります。
import { useState } from 'react';
// ❌ 誤り: list は never[] と推論される
const [list, setList] = useState([]);
// ✅ 正解: 明示的に型を指定
const [list, setList] = useState<string[]>([]);
const addItem = () => {
setList([...list, "new item"]);
};
4. 型アサーション(注意して使用)宣言を簡単に変更できないレガシーコードを扱っている場合は、as キーワードを使用できます。これは TypeScript に「私を信じて」と伝えるものですが、いくつかの安全チェックをバイパスしてしまいます。
const data = [] as string[];
data.push("safe now");
複数の型の処理(Union 型)配列に柔軟性が必要な場合もあります。ID と名前の両方を保存したい場合は、Union 型を使用します。これを行わないと、厳密に型指定された配列に 2 つ目のデータ型を追加しようとした瞬間にコードが壊れてしまいます。
// 文字列と数値の両方を許可
const mixedData: (string | number)[] = [];
mixedData.push("User_01");
mixedData.push(550);
修正を確認する方法エラーが消えたことをただ信じるだけでなく、以下の手順で確認しましょう。
- ホバー状態を確認する: VS Code で変数にマウスを合わせます。
never[]ではなくstring[]と表示されているはずです。- コンパイラを実行する: ターミナルを開き、npx tscを実行します。修正が成功していれば、ビルド出力にエラーは表示されません。- Intellisense をテストする:items.push(と入力します。IDE が正しいデータ型を自動的に提案するはずです。## 予防のためのヒント- 単なる初期化子を避ける:const arr: Type[] = []と書く習慣をつけましょう。これには 2 秒しかかかりませんが、デバッグの時間を大幅に節約できます。- 厳密モード(Strict Mode)を有効にする:tsconfig.jsonで"strict": trueが設定されていることを確認してください。コンパイラはより厳格になりますが、本番環境に到達する前に推論のバグをキャッチできます。- データから始める:const names = ["Admin"];のように、配列を値で初期化すれば、TypeScript は特別な手間をかけずに型をstring[]と正しく推論します。

