エラーメッセージの意味を読み解く
「Cannot read properties of undefined」は、undefinedになっている値からプロパティやメソッドを読み取ろうとしたときに発生する代表的なTypeErrorです。V8系の環境では、読み取ろうとしたプロパティ名を含む形式で表示されることがあります。実際の文言や表示位置は、ブラウザーやNode.jsなどの実行環境によって異なります。
const user = undefined;
console.log(user);
// 出力例: undefined
console.log(user.name);
// 代表的なエラー例:
// TypeError: Cannot read properties of undefined (reading 'name')ポイントは、user自体を表示する処理と、user.nameのようにundefinedのプロパティを参照する処理では結果が異なることです。
undefinedになる代表的な原因を確認する
値がundefinedになる原因には、初期化前の参照、存在しないプロパティや配列要素へのアクセス、値を返さない関数などがあります。
const user = {};
console.log(user.name);
// 出力例: undefined
const users = [{ name: 'Aki' }];
console.log(users[1].name);
// エラー例: users[1] が undefined のため、name を読めない
function createUser() {
// return がないため、戻り値は undefined
}
const createdUser = createUser();
console.log(createdUser.name);
// エラー例: createdUser が undefinedAPIレスポンスや非同期処理では、データ取得前に参照していないか、実際のレスポンス構造と想定が一致しているかを確認します。調査時は、エラー行の参照対象を一時的に表示し、その値の生成箇所までさかのぼると原因を切り分けやすくなります。
console.log('参照前の値:', user);
console.log(user.name);条件分岐で値の存在を確認する
値が存在する場合だけ処理するなら、条件分岐で明示的に確認できます。必須データが欠けたときにエラーを通知したい場合にも適しています。
const user = undefined;
if (user && user.name) {
console.log(user.name);
} else {
console.log('ユーザー名がありません');
}
// 出力: ユーザー名がありません
const name = user && user.name || '名前なし';
console.log(name);
// 出力: 名前なし代替値には||と??を使い分けます。||は空文字、0、falseも代替値に置き換えます。一方、??はnullまたはundefinedの場合だけ右辺を使います。
Optional Chainingで安全にプロパティを参照する
Optional Chainingの?.を使うと、途中の値がnullまたはundefinedの場合にエラーを発生させず、undefinedを返せます。ネストしたデータを短く参照したい場合に便利です。
const user = undefined;
console.log(user?.name);
// 出力: undefined
console.log(user?.profile?.email ?? 'メールアドレスなし');
// 出力: メールアドレスなし
const count = 0;
console.log(count || 10);
// 出力: 10
console.log(count ?? 10);
// 出力: 0ただし、Optional Chainingはデータの欠落原因を解決する機能ではありません。値がない状態を許容して処理を継続する記法なので、必須データが欠けた場合は条件分岐でエラーを通知するなど、要件に合わせて使います。
| 書き方 | 特徴 | 向いている場面 |
|---|---|---|
| 通常のドット記法 | 値がないとエラーになる | 値が必ず存在する設計 |
| 条件分岐 | 欠落時の処理を明示しやすい | 必須データの検証やエラー通知 |
| Optional Chaining | 欠落時にundefinedを返す | 省略可能なデータの参照 |
エラーを再発させない設計とデバッグの進め方
まず、APIや関数の戻り値について、必ず存在する値と欠ける可能性がある値を整理します。そのうえで、データ取得後に処理を開始する、初期値を用意する、必要な値がなければエラーとして通知する、といった方針を決めます。
flowchart TD
A[エラー行を特定] --> B[参照対象を確認]
B --> C[値の生成経路を確認]
C --> D[想定外データをテスト]
D --> E[条件分岐または初期値を設計]図を表示できませんでした。Mermaidコードを確認してください。
デバッグでは、エラー行だけを修正するのではなく、参照対象がどこでundefinedになったかを確認することが重要です。Optional Chainingで黙って処理を続けるのか、条件分岐で異常を検知するのかを、データの重要度に応じて選択しましょう。