TypeScriptで開発していると、ターミナルやエディタに赤いエラーメッセージが表示されて手が止まった経験はありませんか? Type 'string' is not assignable to type 'number'、Object is possibly 'undefined'、Property 'x' does not exist on type 'Y'――これらのエラーメッセージは英語で書かれており、初めて見ると何を言っているのか分からないかもしれません。
しかし、TypeScriptのエラーメッセージには明確なパターンがあります。エラーコード(TS2322、TS2345 など)ごとに原因と解決策が決まっており、読み方さえ分かれば素早く的確に修正できるようになります。
この記事では、TypeScriptで最も遭遇頻度の高いエラーを網羅的に取り上げ、それぞれについてエラーメッセージの読み方、原因、NGコードとOKコードの対比、実践的な解決方法を解説します。エラーが出たときにこの記事を辞書的に参照すれば、すぐに解決の糸口が見つかるはずです。
この記事で学べること
- TypeScriptのエラーメッセージの読み方と構造(TSxxxx コードの意味)
- TS2322: Type ‘X’ is not assignable to type ‘Y’ の原因と解決
- TS2345: Argument of type ‘X’ is not assignable to parameter of type ‘Y’
- TS2339: Property ‘X’ does not exist on type ‘Y’
- TS2532 / TS2531: Object is possibly ‘undefined’ / ‘null’
- TS7006: Parameter ‘X’ implicitly has an ‘any’ type
- TS2304: Cannot find name ‘X’
- TS2769: No overload matches this call
- TS2741: Property ‘X’ is missing in type ‘Y’
- TS2352: Conversion of type ‘X’ to type ‘Y’ may be a mistake
- TS2556: A spread argument must either have a tuple type
- TS18046: ‘X’ is of type ‘unknown’
- TS2349: This expression is not callable
- TS1005 / TS1003 等の構文エラー
- tsconfig.json 関連の設定エラーとベストプラクティス
- 型定義ファイル(.d.ts)関連のエラー(TS7016 等)
- エラー解決のデバッグテクニック集(型の確認方法、satisfies 演算子、// @ts-expect-error 等)
- エラーコード早見表
TypeScriptのエラーメッセージの読み方
TypeScriptのエラーを効率よく解決するためには、まずエラーメッセージの構造を理解することが重要です。一見すると長くて難解に見えるエラーメッセージも、パーツごとに分解すれば読み取れるようになります。
エラーコード(TSxxxx)の意味
TypeScriptのすべてのエラーには TSxxxx 形式の一意のエラーコードが割り振られています。このコードを知っておくと、エラーの種類がすぐに分かり、検索もしやすくなります。
| コード範囲 |
種類 |
説明 |
| TS1xxx |
構文エラー |
括弧の閉じ忘れ、セミコロン不足、予約語の誤用など |
| TS2xxx |
型エラー(セマンティクス) |
型の不一致、存在しないプロパティ、null/undefined チェックなど(最も多い) |
| TS4xxx |
宣言ファイル生成 |
.d.ts ファイルの生成に関連するエラー |
| TS5xxx |
コンパイラ設定 |
tsconfig.json の設定値に関連するエラー |
| TS6xxx |
コンパイラ情報 |
コンパイラの内部情報やメッセージ |
| TS7xxx |
strict モード関連 |
noImplicitAny、strictNullChecks 等の strict 設定に関連 |
| TS18xxx |
最新機能関連 |
unknown 型、const assertion など比較的新しい機能に関連 |
エラーメッセージの構造を分解する
TypeScriptのエラーメッセージは、次のような構造になっています。
エラーメッセージの構造
// ターミナル(tsc コマンド)での表示例
src/app.ts(10,3): error TS2322: Type 'string' is not assignable to type 'number'.
// 分解すると:
// src/app.ts(10,3) → ファイル名(10行目、3文字目)
// error → エラーレベル
// TS2322 → エラーコード
// Type 'string'... → エラーメッセージ本文
VS Code でのエラー確認方法
VS Code を使っている場合は、以下の方法でエラーを確認できます。
| 方法 |
操作 |
特徴 |
| 赤い波線にホバー |
エラー箇所にマウスを重ねる |
最も手軽。エラーコードも表示される |
| Problems パネル |
Ctrl + Shift + M |
プロジェクト全体のエラーを一覧で確認 |
| Quick Fix |
Ctrl + .(エラー箇所で) |
自動修正の候補を表示 |
| ターミナル |
npx tsc --noEmit |
コマンドラインで全エラーを確認 |
ポイント:エラーが出たら、まずエラーコード(TSxxxx)を確認しましょう。同じコードのエラーは必ず同じカテゴリの問題なので、解決パターンが共通しています。この記事ではエラーコードごとに解説しているので、コードを検索すればすぐに該当セクションに辿り着けます。
エラーメッセージでよく使われる英語表現
TypeScriptのエラーメッセージに頻出する英語表現を押さえておくと、初見のエラーでも意味を推測できるようになります。
| 英語表現 |
意味 |
よく出るエラー |
| is not assignable to |
〜に代入できない |
TS2322, TS2345 |
| does not exist on type |
型に存在しない |
TS2339 |
| is possibly ‘undefined’ |
undefined の可能性がある |
TS2532 |
| implicitly has an ‘any’ type |
暗黙的に any 型になっている |
TS7006 |
| cannot find name |
名前が見つからない |
TS2304 |
| is missing in type |
型に足りないプロパティがある |
TS2741 |
| no overload matches |
一致するオーバーロードがない |
TS2769 |
| is of type ‘unknown’ |
unknown 型である |
TS18046 |
TS2322: Type ‘X’ is not assignable to type ‘Y’
TS2322 は TypeScript で最も遭遇頻度が高いエラーです。「型 X を型 Y に代入することはできません」という意味で、変数への代入、オブジェクトのプロパティ設定、関数の戻り値など、あらゆる場面で発生します。
注意:TS2322 はエラーの「結果」を示しているだけです。根本原因は「なぜその型の値が入ってしまうのか」にあります。エラーメッセージの X(実際の型)と Y(期待される型)をよく読み比べましょう。
パターン1: 基本型の不一致
最もシンプルなケースです。変数に宣言した型と異なる型の値を代入しようとしたときに発生します。
NG: 基本型の不一致
let age: number = "twenty";
// Error: Type 'string' is not assignable to type 'number'. (TS2322)
let isActive: boolean = 1;
// Error: Type 'number' is not assignable to type 'boolean'. (TS2322)
OK: 正しい型の値を代入
let age: number = 20;
let isActive: boolean = true;
パターン2: オブジェクト型のプロパティ不一致
オブジェクトのプロパティの型が一致しない場合にも TS2322 が発生します。
NG: プロパティの型不一致
interface User {
name: string;
age: number;
}
const user: User = {
name: "Alice",
age: "25", // Error: Type 'string' is not assignable to type 'number'. (TS2322)
};
OK: 正しい型のプロパティ値
const user: User = {
name: "Alice",
age: 25, // OK: number 型
};
パターン3: Union型との不一致
Union型(|)を使った変数に、Unionのどれにも含まれない型を代入しようとした場合です。
NG: Union型に含まれない値
type Status = "active" | "inactive" | "pending";
const status: Status = "deleted";
// Error: Type '"deleted"' is not assignable to type 'Status'. (TS2322)
OK: Union型に含まれる値 / Union型を拡張
// 解決策1: Union に含まれる値を使う
const status: Status = "active";
// 解決策2: Union 型自体を拡張する
type Status = "active" | "inactive" | "pending" | "deleted";
パターン4: 関数の戻り値型の不一致
関数で宣言した戻り値の型と、実際に return している値の型が異なるケースです。
NG: 戻り値の型が一致しない
function getAge(): number {
return "25";
// Error: Type 'string' is not assignable to type 'number'. (TS2322)
}
function findUser(id: number): User {
if (id === 0) {
return null;
// Error: Type 'null' is not assignable to type 'User'. (TS2322)
}
return { name: "Alice", age: 25 };
}
OK: 戻り値の型を正しく設定
function getAge(): number {
return 25;
}
// null を返す可能性がある場合は戻り値型に含める
function findUser(id: number): User | null {
if (id === 0) {
return null;
}
return { name: "Alice", age: 25 };
}
パターン5: 配列型の不一致
配列に異なる型の要素を含めようとした場合です。
NG: 配列型の不一致
const numbers: number[] = [1, 2, "3"];
// Error: Type 'string' is not assignable to type 'number'. (TS2322)
OK: 型を統一 / Union型の配列にする
// 解決策1: 型を統一する
const numbers: number[] = [1, 2, 3];
// 解決策2: Union 型の配列にする
const items: (number | string)[] = [1, 2, "3"];
TS2322 の解決チェックリスト
TS2322 を解決するためのチェックリスト
- エラーメッセージのX(実際の型)とY(期待される型)を確認する
- 値そのものを修正する(正しい型の値に変更)
- 型注釈を修正する(変数の型宣言を実態に合わせる)
- Union 型に追加する(
null を返すなら Type | null に変更)
- 型アサーション(
as)を使う(最終手段 ― 型安全性が下がるので慎重に)
TS2345: Argument of type ‘X’ is not assignable to parameter of type ‘Y’
TS2345 は関数の引数に関するエラーです。関数を呼び出すとき、渡した引数の型がパラメータの型と一致しない場合に発生します。TS2322 が「代入先」に焦点を当てるのに対し、TS2345 は「引数」に焦点を当てています。
パターン1: 基本的な引数の型不一致
NG: 引数の型が一致しない
function greet(name: string): string {
return `Hello, ${name}!`;
}
greet(42);
// Error: Argument of type 'number' is not assignable to
// parameter of type 'string'. (TS2345)
OK: 正しい型の引数を渡す
greet("Alice"); // OK
greet(String(42)); // OK: 数値を文字列に変換してから渡す
パターン2: Union型の引数に対して広い型を渡す
NG: string を Union リテラル型に渡す
function setTheme(theme: "light" | "dark"): void {
// ...
}
const userTheme = "light"; // 型推論: string(letの場合)
// let で宣言すると string 型に推論される
let userTheme2 = "light"; // 型: string
setTheme(userTheme2);
// Error: Argument of type 'string' is not assignable to
// parameter of type '"light" | "dark"'. (TS2345)
OK: リテラル型として推論させる
// 解決策1: const で宣言(リテラル型に推論される)
const userTheme = "light"; // 型: "light"
setTheme(userTheme); // OK
// 解決策2: as const を使う
let userTheme2 = "light" as const; // 型: "light"
setTheme(userTheme2); // OK
// 解決策3: 明示的に型注釈する
let userTheme3: "light" | "dark" = "light";
setTheme(userTheme3); // OK
パターン3: コールバック関数の型不一致
NG: コールバックの戻り値型が一致しない
const nums = [1, 2, 3];
// map は (value: number) => string 型のコールバックを期待
const result: string[] = nums.map((n) => n * 2);
// Error: Type 'number' is not assignable to type 'string'. (TS2322)
OK: 戻り値の型を合わせる
// 解決策1: 結果の型を正しくする
const result: number[] = nums.map((n) => n * 2);
// 解決策2: コールバックで文字列に変換する
const result2: string[] = nums.map((n) => String(n * 2));
パターン4: null / undefined を受け付けない引数
NG: null の可能性がある値を渡す
function processName(name: string): string {
return name.toUpperCase();
}
const input: string | null = getUserInput();
processName(input);
// Error: Argument of type 'string | null' is not assignable to
// parameter of type 'string'. (TS2345)
OK: null チェックしてから渡す
const input: string | null = getUserInput();
// 解決策1: null チェック(型ガード)
if (input !== null) {
processName(input); // OK: この時点で input は string
}
// 解決策2: デフォルト値を使う
processName(input ?? "Guest"); // OK: null の場合は "Guest"
// 解決策3: 非nullアサーション(確実に null でないと分かっている場合のみ)
processName(input!); // OK(ただし null なら実行時エラー)
注意:非nullアサーション(!)は型チェックを黙らせるだけで、実際に null であれば実行時エラーが発生します。null チェックやデフォルト値を使う方が安全です。
TS2345 の解決チェックリスト
TS2345 を解決するためのチェックリスト
- 関数のパラメータの型定義を確認する(ホバーで確認可能)
- 渡そうとしている値の実際の型を確認する
let を const に変更してリテラル型推論を得る
as const でリテラル型にする
null / undefined チェックで型を絞り込む
- デフォルト値(
??)を使って null / undefined を排除する
TS2339: Property ‘X’ does not exist on type ‘Y’
TS2339 は、オブジェクトに存在しないプロパティにアクセスしようとしたときに発生するエラーです。JavaScript では存在しないプロパティにアクセスしても undefined が返るだけですが、TypeScript はこれをコンパイル時にエラーとして検出します。
パターン1: タイプミス・存在しないプロパティ
NG: 存在しないプロパティにアクセス
interface User {
name: string;
age: number;
}
const user: User = { name: "Alice", age: 25 };
console.log(user.email);
// Error: Property 'email' does not exist on type 'User'. (TS2339)
console.log(user.nmae);
// Error: Property 'nmae' does not exist on type 'User'.
// Did you mean 'name'? (TS2339)
OK: 正しいプロパティ名を使う / 型定義を拡張する
// 解決策1: タイプミスを修正
console.log(user.name); // OK
// 解決策2: 型定義にプロパティを追加
interface User {
name: string;
age: number;
email?: string; // オプショナルとして追加
}
パターン2: Union型のプロパティアクセス
Union型のオブジェクトに対して、一部の型にしか存在しないプロパティにアクセスしようとした場合です。
NG: Union型で共通でないプロパティにアクセス
interface Dog {
kind: "dog";
bark(): void;
}
interface Cat {
kind: "cat";
meow(): void;
}
type Animal = Dog | Cat;
function makeSound(animal: Animal) {
animal.bark();
// Error: Property 'bark' does not exist on type 'Animal'.
// Property 'bark' does not exist on type 'Cat'. (TS2339)
}
OK: 型ガード(Discriminated Union)で絞り込む
function makeSound(animal: Animal) {
if (animal.kind === "dog") {
animal.bark(); // OK: この時点で animal は Dog
} else {
animal.meow(); // OK: この時点で animal は Cat
}
}
パターン3: DOM要素のプロパティ
document.getElementById 等で取得した要素は HTMLElement | null 型なので、特定の要素のプロパティ(value 等)にはアクセスできません。
NG: HTMLElement に value プロパティはない
const input = document.getElementById("username");
console.log(input.value);
// Error: Property 'value' does not exist on type 'HTMLElement'. (TS2339)
OK: 適切な型にキャスト / instanceof で絞り込み
// 解決策1: 型アサーション
const input = document.getElementById("username") as HTMLInputElement;
console.log(input.value); // OK
// 解決策2: instanceof による型ガード(より安全)
const el = document.getElementById("username");
if (el instanceof HTMLInputElement) {
console.log(el.value); // OK: el は HTMLInputElement
}
ポイント:TS2339 が出たら、まずプロパティ名のタイプミスを疑いましょう。TypeScriptは「Did you mean ‘xxx’?」と候補を提示してくれることもあります。タイプミスでなければ、型定義の見直しか型ガードによる絞り込みが必要です。
TS2532 / TS2531: Object is possibly ‘undefined’ / ‘null’
TS2532(Object is possibly ‘undefined’)と TS2531(Object is possibly ‘null’)は、strictNullChecks が有効な環境で最も頻繁に遭遇するエラーです。undefined や null の可能性がある値に対してメソッド呼び出しやプロパティアクセスを行おうとすると発生します。
注意:このエラーは strictNullChecks: true(または strict: true)のときにのみ発生します。false の場合は発生しませんが、実行時エラーのリスクが高まるため、strictNullChecks は有効にすることを強く推奨します。
パターン1: 配列の find メソッド
Array.find() は条件に一致する要素が見つからない場合 undefined を返します。そのため戻り値は常に T | undefined です。
NG: find の結果をそのまま使う
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
];
const user = users.find((u) => u.id === 3);
// 型: { id: number; name: string } | undefined
console.log(user.name);
// Error: Object is possibly 'undefined'. (TS2532)
OK: undefined チェックの方法(5通り)
// 解決策1: if 文で undefined チェック
if (user) {
console.log(user.name); // OK
}
// 解決策2: Optional Chaining(?.)
console.log(user?.name); // OK: undefined なら undefined を返す
// 解決策3: Nullish Coalescing(??)でデフォルト値
console.log(user?.name ?? "Unknown"); // OK: undefined なら "Unknown"
// 解決策4: 非nullアサーション(確実に存在すると分かっている場合のみ)
console.log(user!.name); // OK(ただし undefined なら実行時エラー)
// 解決策5: 早期 return パターン
if (!user) {
throw new Error("User not found");
}
console.log(user.name); // OK: ここに到達するなら user は存在する
パターン2: Map の get メソッド
NG: Map.get() の結果をそのまま使う
const map = new Map<string, number>();
map.set("a", 1);
const value = map.get("a"); // 型: number | undefined
const result = value * 2;
// Error: Object is possibly 'undefined'. (TS2532)
OK: undefined チェック / デフォルト値を使う
// 解決策1: undefined チェック
const value = map.get("a");
if (value !== undefined) {
const result = value * 2; // OK
}
// 解決策2: デフォルト値
const result = (map.get("a") ?? 0) * 2; // OK: undefined なら 0
パターン3: DOM要素の取得
NG: DOM要素の null チェックなし
const button = document.querySelector("#submit");
// 型: Element | null
button.addEventListener("click", () => { });
// Error: Object is possibly 'null'. (TS2531)
OK: null チェックしてから使う
const button = document.querySelector("#submit");
// 解決策1: null チェック
if (button) {
button.addEventListener("click", () => { });
}
// 解決策2: Optional Chaining
button?.addEventListener("click", () => { });
// 解決策3: 非nullアサーション(HTMLに確実に存在する場合のみ)
const button2 = document.querySelector("#submit")!;
button2.addEventListener("click", () => { });
TS2532 / TS2531 の解決パターン比較
| 解決方法 |
書き方 |
安全性 |
使い分け |
| if チェック |
if (x) { ... } |
最も安全 |
値が存在するときだけ処理したい場合 |
| Optional Chaining |
x?.prop |
安全 |
アクセスだけしたい(結果が undefined でもOK) |
| Nullish Coalescing |
x ?? default |
安全 |
デフォルト値を使いたい場合 |
| 早期 return / throw |
if (!x) throw ... |
安全 |
存在しないのがエラーの場合 |
| 非nullアサーション |
x! |
危険 |
確実に null/undefined でないと分かっている場合のみ |
TS7006: Parameter ‘X’ implicitly has an ‘any’ type
TS7006 は、関数のパラメータに型注釈がない場合に発生するエラーです。TypeScript の noImplicitAny(または strict)オプションが有効な環境で、型を推論できないパラメータがあると警告されます。
なぜ noImplicitAny が重要なのか
any 型は型チェックを完全にスキップするため、バグの温床になる
- パラメータに型注釈がないと、関数の使い方が分からなくなる
noImplicitAny: true により、「意図しない any」を防止できる
- 新規プロジェクトでは
strict: true(noImplicitAny を含む)がベストプラクティス
パターン1: 関数パラメータの型注釈なし
NG: パラメータに型注釈がない
function greet(name) {
// Error: Parameter 'name' implicitly has an 'any' type. (TS7006)
return `Hello, ${name}!`;
}
const add = (a, b) => a + b;
// Error: Parameter 'a' implicitly has an 'any' type. (TS7006)
// Error: Parameter 'b' implicitly has an 'any' type. (TS7006)
OK: 型注釈を追加する
function greet(name: string): string {
return `Hello, ${name}!`;
}
const add = (a: number, b: number): number => a + b;
パターン2: コールバック関数(エラーにならないケース)
コールバック関数のパラメータは、親関数の型定義から型が推論されるため、通常は型注釈なしでも TS7006 は発生しません。
コールバックでは型推論が効く
const numbers = [1, 2, 3];
// n の型は number と推論される(TS7006 は発生しない)
numbers.map((n) => n * 2); // OK
// forEach のコールバックも同様
numbers.forEach((value, index) => {
console.log(value, index); // OK: value: number, index: number
});
パターン3: イベントハンドラの型注釈
NG: イベントハンドラの型注釈がない
const handleClick = (event) => {
// Error: Parameter 'event' implicitly has an 'any' type. (TS7006)
console.log(event.target);
};
OK: イベントの型を明示する
// 解決策1: パラメータに型注釈
const handleClick = (event: MouseEvent) => {
console.log(event.target); // OK
};
// 解決策2: React の場合
const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
console.log(event.currentTarget); // OK
};
ポイント:TS7006 の解決は単純です。パラメータに型注釈を付けるだけです。ただし、コールバック関数のように型推論が効く場面では型注釈は不要です。「どこに型注釈が必要か」を見極めることが大切です。
TS2304: Cannot find name ‘X’
TS2304 は、TypeScript が変数名・型名・関数名を見つけられない場合に発生するエラーです。原因は多岐にわたり、単純なタイプミスから import 忘れ、型定義ファイルの不足まで様々です。
パターン1: import 忘れ
NG: import なしで使用
// React の import を忘れている
const App: React.FC = () => {
return <div>Hello</div>;
};
// Error: Cannot find name 'React'. (TS2304)
OK: 必要な import を追加
import React from "react";
const App: React.FC = () => {
return <div>Hello</div>;
};
パターン2: グローバル変数の型が定義されていない
NG: グローバル変数を直接参照
// ブラウザのグローバル変数やサードパーティのグローバル
console.log(__dirname);
// Error: Cannot find name '__dirname'. (TS2304)
console.log(process.env.NODE_ENV);
// Error: Cannot find name 'process'. (TS2304)
OK: 型定義をインストール / 宣言する
// 解決策1: Node.js の型定義をインストール
// npm install --save-dev @types/node
// 解決策2: declare で型を宣言
declare const __dirname: string;
// 解決策3: tsconfig.json の lib / types を確認
// {
// "compilerOptions": {
// "types": ["node"]
// }
// }
パターン3: tsconfig.json の lib 設定不足
Promise、Map、Set などの ES2015+ の組み込み型を使おうとしたとき、lib 設定に含まれていないとエラーになります。
NG: lib に ES2015 が含まれていない
// tsconfig.json: { "compilerOptions": { "lib": ["ES5"] } }
const p = new Promise((resolve) => resolve(1));
// Error: Cannot find name 'Promise'. (TS2304)
OK: lib に必要なターゲットを追加
// tsconfig.json
{
"compilerOptions": {
"lib": ["ES2020", "DOM"]
}
}
ポイント:TS2304 が出たら、(1) import 忘れ、(2) @types パッケージ未インストール、(3) tsconfig.json の lib / types 設定不足 の3つを順番に確認しましょう。VS Code の Quick Fix(Ctrl + .)が import を自動追加してくれることもあります。
TS2769: No overload matches this call
TS2769 は、オーバーロードされた関数を呼び出したとき、どのオーバーロード定義にも引数が一致しない場合に発生するエラーです。このエラーは特に React の useState、useRef、DOM API、ライブラリの関数などでよく見かけます。
パターン1: React の useState
NG: useState に型と一致しない初期値を渡す
interface User {
id: number;
name: string;
}
// 初期値 null を渡しているが、型引数に null が含まれていない
const [user, setUser] = useState<User>(null);
// Error: No overload matches this call. (TS2769)
OK: 型引数に null を含める
// 解決策: 型引数に null を含める
const [user, setUser] = useState<User | null>(null);
// OK: user の型は User | null
パターン2: addEventListener のイベント型
NG: 存在しないイベント名を渡す
document.addEventListener("clik", (e) => { });
// Error: No overload matches this call.
// Overload 1 of 2: addEventListener(type: keyof DocumentEventMap, ...)
// '"clik"' is not assignable to parameter of type 'keyof DocumentEventMap'
// (TS2769)
OK: 正しいイベント名を使う
document.addEventListener("click", (e) => {
console.log(e.clientX, e.clientY); // OK: e は MouseEvent
});
パターン3: 複数のオーバーロードがある関数
NG: どのオーバーロードにも一致しない引数
// 自作のオーバーロード関数
function format(value: string): string;
function format(value: number, digits: number): string;
function format(value: any, digits?: number): string {
return typeof value === "number"
? value.toFixed(digits)
: value;
}
format(true);
// Error: No overload matches this call.
// Overload 1: format(value: string): string
// Overload 2: format(value: number, digits: number): string (TS2769)
OK: いずれかのオーバーロードに一致する引数を渡す
format("hello"); // OK: Overload 1 に一致
format(3.14159, 2); // OK: Overload 2 に一致
ポイント:TS2769 のエラーメッセージは長くなりがちですが、各オーバーロード候補とその不一致理由が順番に表示されます。最初のオーバーロード候補の不一致理由を読むだけで原因が分かることが多いです。
TS2741: Property ‘X’ is missing in type ‘Y’ but required in type ‘Z’
TS2741 は、オブジェクトに必須プロパティが足りない場合に発生するエラーです。interface や type で定義された必須プロパティが、実際のオブジェクトに含まれていないときに表示されます。
パターン1: オブジェクトリテラルのプロパティ不足
NG: 必須プロパティが不足
interface Config {
host: string;
port: number;
ssl: boolean;
}
const config: Config = {
host: "localhost",
port: 3000,
// Error: Property 'ssl' is missing in type
// '{ host: string; port: number; }' but required in type 'Config'. (TS2741)
};
OK: 不足プロパティを追加 / オプショナルにする
// 解決策1: 不足しているプロパティを追加
const config: Config = {
host: "localhost",
port: 3000,
ssl: false, // 追加
};
// 解決策2: プロパティをオプショナルにする
interface Config {
host: string;
port: number;
ssl?: boolean; // ? を付けてオプショナルに
}
// 解決策3: Partial を使ってすべてオプショナルにする
const partialConfig: Partial<Config> = {
host: "localhost",
};
パターン2: React コンポーネントの Props 不足
NG: 必須 Props を渡していない
interface ButtonProps {
label: string;
onClick: () => void;
disabled: boolean;
}
function Button(props: ButtonProps) {
return <button>{props.label}</button>;
}
// disabled が不足
<Button label="送信" onClick={() => {}} />
// Error: Property 'disabled' is missing... (TS2741)
OK: Props をすべて渡す / デフォルト値を設定
// 解決策1: 全 Props を渡す
<Button label="送信" onClick={() => {}} disabled={false} />
// 解決策2: Props にデフォルト値を設定
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean; // オプショナルに変更
}
function Button({ label, onClick, disabled = false }: ButtonProps) {
return <button disabled={disabled} onClick={onClick}>{label}</button>;
}
ポイント:TS2741 のエラーメッセージには「何が足りないのか」が明確に書かれています。不足プロパティを追加するか、型定義側で ? を付けてオプショナルにするかの判断がポイントです。Partial<T> ユーティリティ型を活用する手もあります。
TS2352: Conversion of type ‘X’ to type ‘Y’ may be a mistake
TS2352 は、型アサーション(as)を使ったとき、変換元と変換先の型に互換性がない場合に発生するエラーです。TypeScript は明らかに間違った型アサーションを防止してくれます。
パターン1: 互換性のない型同士のアサーション
NG: string を number にアサーション
const str = "hello";
const num = str as number;
// Error: Conversion of type 'string' to type 'number' may be a mistake
// because neither type sufficiently overlaps with the other.
// If this was intentional, convert the expression to 'unknown' first. (TS2352)
OK: 正しい変換方法
const str = "42";
// 解決策1: 実際に値を変換する(推奨)
const num = Number(str); // 型: number
// 解決策2: unknown を経由する(本当に必要な場合のみ)
const num2 = str as unknown as number; // 危険!型安全性が失われる
注意:as unknown as T はダブルアサーション(二重アサーション)と呼ばれ、TypeScriptの型チェックを完全に迂回します。テストコードやレガシーコードの一時的な対処以外では使用を避けるべきです。
パターン2: オブジェクト型同士のアサーション
NG: 互換性のないオブジェクト型へのアサーション
interface Dog { breed: string; bark(): void; }
interface Car { make: string; drive(): void; }
const dog: Dog = { breed: "Shiba", bark() {} };
const car = dog as Car;
// Error: Conversion of type 'Dog' to type 'Car' may be a mistake. (TS2352)
OK: 型設計を見直す
// 型設計を見直して、正しい変換ロジックを書く
// そもそも Dog を Car に変換するのは論理的に間違い
// → 正しい型を最初から使うように設計を修正する
TS2556: A spread argument must either have a tuple type or be passed to a rest parameter
TS2556 は、スプレッド構文(...)で配列を関数の引数に展開するとき、配列の型がタプル型でない場合に発生するエラーです。TypeScript は配列の長さと各要素の型が確定していないと、スプレッドを安全と見なしません。
パターン1: 配列をスプレッドで関数引数に渡す
NG: 通常の配列をスプレッドで渡す
function add(a: number, b: number): number {
return a + b;
}
const args = [1, 2]; // 型: number[](長さ不定)
add(...args);
// Error: A spread argument must either have a tuple type
// or be passed to a rest parameter. (TS2556)
OK: タプル型にする / as const を使う
// 解決策1: as const でタプル型にする
const args = [1, 2] as const; // 型: readonly [1, 2]
add(...args); // OK
// 解決策2: 明示的にタプル型を注釈
const args2: [number, number] = [1, 2];
add(...args2); // OK
// 解決策3: rest パラメータを使う関数に変更
function sum(...nums: number[]): number {
return nums.reduce((a, b) => a + b, 0);
}
const numbers = [1, 2, 3];
sum(...numbers); // OK: rest パラメータは配列を受け入れる
ポイント:配列をスプレッドで関数引数に渡したいなら、as const でタプル型にするのが最も手軽です。as const を付けると配列は readonly かつ各要素の型が確定したタプルとして扱われます。
TS18046: ‘X’ is of type ‘unknown’
TS18046 は、unknown 型の値に対して直接操作を行おうとしたときに発生するエラーです。unknown は any の安全版とも言える型で、何の型か分からない値を表しますが、使用する前に型を絞り込む必要があります。
unknown vs any の違い
any: 何でもできる(型チェックをスキップ)→ 危険
unknown: 何の型か分からない → 使う前に型を確認する必要がある → 安全
- 外部からの入力(API レスポンス、JSON.parse、catch のエラーなど)には
unknown を使うのがベストプラクティス
パターン1: try-catch のエラーオブジェクト
TypeScript 4.4 以降、catch 句のエラーはデフォルトで unknown 型になりました。
NG: unknown 型のエラーを直接使う
try {
riskyOperation();
} catch (error) {
// error の型: unknown
console.log(error.message);
// Error: 'error' is of type 'unknown'. (TS18046)
}
OK: 型を絞り込んでから使う
try {
riskyOperation();
} catch (error) {
// 解決策1: instanceof で型ガード
if (error instanceof Error) {
console.log(error.message); // OK: error は Error
console.log(error.stack); // OK
} else {
console.log("Unknown error:", error);
}
}
// 解決策2: 汎用的なエラーハンドラ関数を作る
function getErrorMessage(error: unknown): string {
if (error instanceof Error) return error.message;
if (typeof error === "string") return error;
return "An unknown error occurred";
}
パターン2: JSON.parse の戻り値
unknown 型のデータを安全に扱う
// JSON.parse の戻り値は any だが、unknown として扱うのが安全
function parseConfig(json: string): AppConfig {
const data: unknown = JSON.parse(json);
// 型ガードで安全に検証
if (
typeof data === "object" &&
data !== null &&
"host" in data &&
"port" in data
) {
return data as AppConfig;
}
throw new Error("Invalid config format");
}
unknown 型の絞り込みパターン一覧
| 絞り込み方法 |
書き方 |
用途 |
| typeof |
typeof x === "string" |
プリミティブ型の判定 |
| instanceof |
x instanceof Error |
クラスインスタンスの判定 |
| in 演算子 |
"prop" in x |
プロパティの存在チェック |
| Array.isArray |
Array.isArray(x) |
配列かどうかの判定 |
| カスタム型ガード |
function isX(v): v is X |
複雑な型の判定 |
TS2349: This expression is not callable
TS2349 は、関数ではない値を関数として呼び出そうとしたときに発生するエラーです。変数の型が関数型でないのに () を付けて呼び出そうとすると表示されます。
パターン1: プロパティの値が関数ではない
NG: 関数でない値を呼び出す
interface Config {
port: number;
host: string;
}
const config: Config = { port: 3000, host: "localhost" };
config.port();
// Error: This expression is not callable.
// Type 'Number' has no call signatures. (TS2349)
OK: プロパティへのアクセスと関数呼び出しを区別
// プロパティの値を参照するだけなら () は不要
console.log(config.port); // OK: 3000
// 関数として使いたいなら型定義を変更する
interface Config {
getPort: () => number; // 関数型のプロパティ
host: string;
}
パターン2: Union型で一部が関数でない
NG: Union型の値を呼び出す
type Handler = (() => void) | string;
const handler: Handler = () => console.log("done");
handler();
// Error: This expression is not callable.
// Not all constituents of type 'Handler' are callable. (TS2349)
OK: typeof で関数かどうか確認してから呼び出す
if (typeof handler === "function") {
handler(); // OK: この時点で handler は () => void
} else {
console.log(handler); // OK: この時点で handler は string
}
パターン3: import ミス
モジュールの default export と named export を間違えてインポートした場合にもこのエラーが発生します。
NG: default export を { } でインポート
// utils.ts は export default function calc() { ... }
import { calc } from "./utils"; // 間違い: named import
calc();
// Error: This expression is not callable. (TS2349)
OK: 正しいインポート方法
// default export は {} なしでインポート
import calc from "./utils";
calc(); // OK
TS1005 / TS1003 等: 構文エラー(Syntax Errors)
TS1xxx 番台のエラーは構文エラーです。コードの書き方が TypeScript(JavaScript)の文法に合っていない場合に発生します。型エラーと違い、コードの構造自体が壊れているので、まず構文を修正する必要があります。
TS1005: ‘X’ expected(’X’ が期待される)
括弧やセミコロンの閉じ忘れなど、TypeScript パーサーが特定のトークンを期待しているのに別のものが来た場合に発生します。
NG: 構文エラーの例
// 閉じ括弧の不足
function add(a: number, b: number {
// Error: ')' expected. (TS1005)
return a + b;
}
// 型注釈のコロン忘れ
let name string = "Alice";
// Error: ';' expected. (TS1005)
// アロー関数の => 忘れ
const fn = (x: number) { return x; };
// Error: '=>' expected. (TS1005)
OK: 正しい構文
function add(a: number, b: number) {
return a + b;
}
let name: string = "Alice"; // コロンを追加
const fn = (x: number) => { return x; }; // => を追加
TS1003: Identifier expected(識別子が期待される)
変数名や関数名が必要な場所に、予約語や記号が来た場合に発生します。
NG: 予約語を変数名に使う
const class = "active";
// Error: Identifier expected. (TS1003)
const return = 42;
// Error: Identifier expected. (TS1003)
OK: 予約語を避ける
const className = "active"; // OK
const result = 42; // OK
構文エラー解決のコツ
構文エラーを素早く解決するコツ
- エラーが指す行番号の少し前を確認する(原因は報告行の前にあることが多い)
- VS Code の括弧のマッチング機能で対応する括弧を確認
- Prettier / ESLint の自動フォーマットで構文の崩れを検出
- 構文エラーが連鎖的に大量発生している場合、最初の1つを修正すれば残りも消えることが多い
- JavaScript の予約語一覧を確認(class, return, const, let, var, function 等)
tsconfig.json 関連のエラーと設定ミス
tsconfig.json はTypeScriptコンパイラの設定ファイルです。この設定が不適切だと、コード自体は正しくてもエラーが発生することがあります。ここでは特に初心者がハマりやすい設定ミスと、推奨設定を解説します。
strict モードの影響
strict: true を有効にすると、以下のフラグがすべて有効になります。
| フラグ |
説明 |
関連エラー |
| strictNullChecks |
null / undefined を明示的にチェック |
TS2531, TS2532 |
| noImplicitAny |
暗黙の any を禁止 |
TS7006 |
| strictFunctionTypes |
関数の引数を厳密にチェック |
TS2345 |
| strictBindCallApply |
bind, call, apply の型チェック |
TS2769 |
| strictPropertyInitialization |
クラスプロパティの初期化を強制 |
TS2564 |
| noImplicitThis |
暗黙の this を禁止 |
TS2683 |
| alwaysStrict |
JavaScript の "use strict" を出力 |
– |
推奨 tsconfig.json(新規プロジェクト向け)
tsconfig.json(推奨設定)
{
"compilerOptions": {
// 型チェックの厳格さ
"strict": true,
// ターゲットとモジュール
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
// 型定義
"lib": ["ES2020", "DOM", "DOM.Iterable"],
// 出力
"outDir": "./dist",
"declaration": true,
// その他推奨設定
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"isolatedModules": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
よくある tsconfig.json のミスとエラー
| ミス |
症状 |
解決策 |
| lib に DOM がない |
document, window 等でエラー |
"lib": ["ES2020", "DOM"] を追加 |
| include パスが間違い |
ファイルが認識されない |
パスを修正("src/**/*" など) |
| module が CommonJS |
import/export の書き方でエラー |
"module": "ESNext" に変更 |
| esModuleInterop が false |
default import でエラー |
"esModuleInterop": true |
| jsx の設定がない |
JSX/TSX でエラー |
"jsx": "react-jsx" を追加 |
ポイント:新規プロジェクトでは strict: true を最初から有効にすることを強く推奨します。既存プロジェクトに strict を導入する場合は、個別フラグ(strictNullChecks など)を一つずつ有効にしていくのが現実的です。
型定義ファイル(.d.ts)関連のエラー
サードパーティのJavaScriptライブラリをTypeScriptで使う場合、型定義ファイル(.d.ts)が必要です。型定義がないと TypeScript はライブラリの型情報を知ることができず、エラーが発生します。
TS7016: Could not find a declaration file for module ‘X’
最も一般的な型定義関連のエラーです。npm パッケージに型定義が含まれておらず、@types パッケージもインストールされていない場合に発生します。
NG: 型定義がないパッケージをインポート
import someLib from "some-untyped-lib";
// Error: Could not find a declaration file for module 'some-untyped-lib'.
// 'node_modules/some-untyped-lib/index.js' implicitly has an 'any' type.
// Try `npm i --save-dev @types/some-untyped-lib` (TS7016)
OK: 型定義をインストール / 自作する
// 解決策1: @types パッケージをインストール
// npm install --save-dev @types/some-untyped-lib
// 解決策2: 自作の型宣言ファイルを作成
// src/types/some-untyped-lib.d.ts
declare module "some-untyped-lib" {
const content: any;
export default content;
}
// 解決策3: より詳細な型定義を書く
declare module "some-untyped-lib" {
export function doSomething(input: string): number;
export interface Config {
debug: boolean;
}
}
型定義ファイルの探し方
| ステップ |
確認方法 |
詳細 |
| 1. パッケージ内蔵 |
package.json の types フィールド |
最近のパッケージは型定義を同梱していることが多い |
| 2. @types パッケージ |
npm i -D @types/xxx |
DefinitelyTyped で管理されている型定義 |
| 3. 型定義検索 |
TypeScript 型定義検索 |
公式サイトで @types パッケージを検索 |
| 4. 自作 |
declare module "xxx" |
上記で見つからない場合は自作する |
グローバル型の拡張(Window など)
サードパーティのスクリプトがグローバル変数を追加する場合(Google Analytics など)、TypeScript はその存在を知らないためエラーになります。
グローバル型を拡張する(global.d.ts)
// src/types/global.d.ts
// Window にプロパティを追加
declare global {
interface Window {
gtag: (...args: any[]) => void;
dataLayer: any[];
}
}
// 環境変数の型定義(Vite の場合)
interface ImportMetaEnv {
readonly VITE_API_URL: string;
readonly VITE_APP_TITLE: string;
}
export {}; // これがないと global 宣言が機能しない
注意:declare global を含むファイルには、必ず export {} などの export 文を含めてください。export がないと TypeScript はそのファイルをスクリプト(モジュールでないファイル)として扱い、declare global が正しく機能しません。
エラー解決のデバッグテクニック集
ここまで個別のエラーコードを見てきましたが、エラー解決には汎用的なテクニックも重要です。VS Code での型の確認方法、一時的な型抑制、型の絞り込みなど、日常的に使えるテクニックをまとめます。
テクニック1: VS Code でホバーして型を確認する
最も基本的かつ強力なテクニックです。変数や関数にマウスをホバーすると、TypeScript が推論した型が表示されます。
ホバーで表示される型情報
const users = [{ name: "Alice", age: 25 }];
// users にホバーすると:
// const users: { name: string; age: number; }[]
const found = users.find(u => u.age > 20);
// found にホバーすると:
// const found: { name: string; age: number; } | undefined
// → undefined が含まれている! だから TS2532 が出る理由が分かる
テクニック2: satisfies 演算子で型を検証する(TypeScript 4.9+)
satisfies は、値が特定の型に適合するかチェックしつつ、推論された型を保持する演算子です。as とは異なり、型を変更せずに検証だけ行います。
satisfies の活用例
type Color = "red" | "green" | "blue";
type ColorMap = Record<Color, string | number[]>;
// as ColorMap を使うと、各値の具体的な型が失われる
const colorsAs = {
red: "#ff0000",
green: [0, 255, 0],
blue: "#0000ff",
} as ColorMap;
colorsAs.red.toUpperCase(); // Error! string | number[] にはない
// satisfies を使うと、型の検証 + 具体的な型の保持
const colorsSatisfies = {
red: "#ff0000",
green: [0, 255, 0],
blue: "#0000ff",
} satisfies ColorMap;
colorsSatisfies.red.toUpperCase(); // OK! red は string と推論
テクニック3: // @ts-expect-error と // @ts-ignore
一時的にエラーを抑制したい場合のコメントディレクティブです。
| ディレクティブ |
動作 |
推奨度 |
// @ts-expect-error |
次の行のエラーを抑制。エラーがなくなると逆にエラーになる |
推奨(テストで有用) |
// @ts-ignore |
次の行のエラーを無条件に抑制 |
非推奨(問題を隠す) |
// @ts-nocheck |
ファイル全体の型チェックを無効化 |
非推奨(移行時の一時的な使用のみ) |
@ts-expect-error の使い方
// テストで意図的にエラーを起こすケース
// @ts-expect-error: テスト用 ― number に string を渡すとエラーになることを確認
add("hello", "world");
// @ts-expect-error は、エラーが解消されると逆にエラーになる
// → これにより「もうエラーは存在しない」ことが分かる(掃除のサイン)
// @ts-expect-error
add(1, 2); // Error: Unused '@ts-expect-error' directive. (TS2578)
テクニック4: 型ユーティリティで型を調査する
型の調査テクニック
// ReturnType で関数の戻り値型を調べる
type FetchResult = ReturnType<typeof fetch>;
// → Promise<Response>
// Parameters で関数のパラメータ型を調べる
type SetTimeoutArgs = Parameters<typeof setTimeout>;
// → [callback: TimerHandler, ms?: number, ...args: any[]]
// keyof でオブジェクトのキー一覧を確認
interface User { id: number; name: string; email: string; }
type UserKeys = keyof User;
// → "id" | "name" | "email"
// Awaited で Promise の中身の型を取得
type Data = Awaited<Promise<string>>;
// → string
テクニック5: npx tsc –noEmit で全体チェック
VS Code のエディタ上ではエラーが表示されていなくても、プロジェクト全体でコンパイルエラーが潜んでいることがあります。
プロジェクト全体の型チェック
# プロジェクト全体を型チェック(コンパイルはしない)
npx tsc --noEmit
# エラー数だけ確認
npx tsc --noEmit 2>&1 | grep "error TS" | wc -l
# 特定のファイルだけチェック
npx tsc --noEmit src/app.ts
# CI/CD パイプラインでの使用
# package.json に追加:
# "scripts": { "typecheck": "tsc --noEmit" }
テクニック6: 段階的な型の絞り込み
エラーが出たとき、変数の型を段階的に確認していくアプローチです。
段階的に型を確認するアプローチ
// Step 1: 一時変数に代入して型を確認
const response = await fetch("/api/users");
// ホバー → const response: Response
// Step 2: 次の処理結果の型を確認
const data = await response.json();
// ホバー → const data: any(ここが問題!)
// Step 3: 型注釈を追加して修正
interface User { id: number; name: string; }
const data: User[] = await response.json();
// ホバー → const data: User[](型が確定!)
エラー解決のフローチャート
- Step 1: エラーコード(TSxxxx)を確認する
- Step 2: エラーメッセージの X(実際の型)と Y(期待される型)を読む
- Step 3: 変数にホバーして、実際に推論されている型を確認する
- Step 4: 原因を特定する(型注釈の間違い?値の間違い?null チェック不足?)
- Step 5: この記事の該当セクションを参照して修正する
まとめ:TypeScript エラーコード早見表
この記事で解説した TypeScript のエラーコードを早見表としてまとめます。エラーが出たときにこの表を参照して、該当するセクションを確認してください。
| エラーコード |
メッセージ |
主な原因 |
解決のキーワード |
| TS2322 |
Type ‘X’ is not assignable to type ‘Y’ |
代入先と値の型不一致 |
型注釈の修正、Union型の拡張 |
| TS2345 |
Argument of type ‘X’ is not assignable to parameter of type ‘Y’ |
関数引数の型不一致 |
as const、型ガード、デフォルト値 |
| TS2339 |
Property ‘X’ does not exist on type ‘Y’ |
存在しないプロパティへのアクセス |
タイプミス確認、型定義の拡張、型ガード |
| TS2532 |
Object is possibly ‘undefined’ |
undefined チェック不足 |
if チェック、?.、??、! |
| TS2531 |
Object is possibly ‘null’ |
null チェック不足 |
if チェック、?.、??、! |
| TS7006 |
Parameter ‘X’ implicitly has an ‘any’ type |
パラメータの型注釈なし |
型注釈を追加する |
| TS2304 |
Cannot find name ‘X’ |
import忘れ、型定義なし |
import追加、@types インストール |
| TS2769 |
No overload matches this call |
オーバーロードと引数の不一致 |
オーバーロード定義の確認 |
| TS2741 |
Property ‘X’ is missing in type ‘Y’ |
必須プロパティの不足 |
プロパティ追加、?、Partial |
| TS2352 |
Conversion of type ‘X’ to type ‘Y’ may be a mistake |
不正な型アサーション |
値の変換、型設計の見直し |
| TS2556 |
A spread argument must have a tuple type |
配列のスプレッドが非タプル |
as const、タプル型注釈 |
| TS18046 |
‘X’ is of type ‘unknown’ |
unknown 型のまま操作 |
typeof、instanceof、in |
| TS2349 |
This expression is not callable |
関数でない値を呼び出し |
() の削除、typeof チェック |
| TS1005 |
‘X’ expected |
括弧・記号の不足 |
構文を修正(括弧、コロン等) |
| TS1003 |
Identifier expected |
予約語を識別子に使用 |
変数名を変更する |
| TS7016 |
Could not find a declaration file |
型定義ファイルがない |
@types インストール、declare module |
TypeScript のエラーメッセージは、慣れてしまえば最も信頼できるデバッグツールです。「エラーが出た = TypeScript が問題を事前に見つけてくれた」と捉えることで、実行時エラーを未然に防ぎ、より堅牢なコードを書くことができます。
エラーへの対処力は TypeScript スキルの核心です。この記事で紹介したパターンとテクニックを使いこなして、エラーに強い TypeScript 開発者を目指しましょう。