TypeError: Cannot read properties of null (reading '...' ) は JavaScript で最も多いエラーの 1 つです。null の変数にプロパティやメソッドでアクセスしようとしたときに発生します。
本記事では、このエラーが発生する5 つの典型パターンと、それぞれの原因特定方法・解決策を解説します。
この記事でわかること
・エラーメッセージの読み方
・発生する 5 つの典型パターンと解決策
・null チェックの書き方(if / オプショナルチェーニング)
・DOMContentLoaded / defer で DOM 取得エラーを防ぐ方法
・console.log でのデバッグ方法
・エラーメッセージの読み方
・発生する 5 つの典型パターンと解決策
・null チェックの書き方(if / オプショナルチェーニング)
・DOMContentLoaded / defer で DOM 取得エラーを防ぐ方法
・console.log でのデバッグ方法
エラーメッセージの読み方
エラーメッセージの例
Uncaught TypeError: Cannot read properties of null (reading 'textContent')
at script.js:5:25
| 部分 | 意味 |
|---|---|
| Cannot read properties of null | 変数が null だった |
| (reading ‘textContent‘) | null に対して .textContent にアクセスしようとした |
| at script.js:5:25 | script.js の 5 行目で発生 |
「何行目」と「何のプロパティ」に注目
エラーメッセージの行番号とプロパティ名を確認すれば、どの変数が null なのかがすぐにわかります。その変数がなぜ null になるかを調査するのが解決の鍵です。
エラーメッセージの行番号とプロパティ名を確認すれば、どの変数が null なのかがすぐにわかります。その変数がなぜ null になるかを調査するのが解決の鍵です。
パターン(1): DOM の読み込み前にスクリプトが実行された
最も多い原因です。HTML がまだ読み込まれていないタイミングで getElementById 等を実行すると null が返ります。
NG: head 内のスクリプト
<!-- NG: body の要素がまだ存在しないタイミングで実行 -->
<head>
<script>
const el = document.getElementById("title"); // null!
el.textContent = "Hello"; // TypeError!
</script>
</head>
<body>
<h1 id="title">World</h1>
</body>
解決策 3 つ
OK(1): DOMContentLoaded で待つ
document.addEventListener("DOMContentLoaded", () => {
const el = document.getElementById("title"); // OK
el.textContent = "Hello";
});
OK(2): defer 属性を使う(推奨)
<!-- HTML パース完了後にスクリプトを実行 --> <head> <script src="app.js" defer></script> </head>
OK(3): body の末尾にスクリプトを置く
<body>
<h1 id="title">World</h1>
<script>
const el = document.getElementById("title"); // OK
</script>
</body>
| 方法 | 推奨度 |
|---|---|
| defer 属性 | 最も推奨(head に書ける + パース完了後に実行) |
| DOMContentLoaded | 推奨(インラインスクリプト向け) |
| body 末尾 | 可(シンプルだが head に書けない) |
パターン(2): ID / クラス名のスペルミス
NG
// HTML: <div id="main-title">
const el = document.getElementById("mainTitle"); // null(ハイフンが抜けている)
el.textContent = "Hello"; // TypeError!
OK
const el = document.getElementById("main-title"); // OK
// querySelector の場合は # が必要: querySelector("#main-title")
デバッグ方法: console.log で null を確認
プロパティアクセスの前に
const el = document.getElementById("xxx");
console.log(el); // null ならここで気づけるプロパティアクセスの前に
console.log を入れて null かどうか確認してください。パターン(3): API レスポンスが null / undefined を含む
NG
const user = await fetchUser(42); // user.address が null の場合 console.log(user.address.city); // TypeError!
OK: null チェック
// if 文でチェック
if (user && user.address) {
console.log(user.address.city);
}
// オプショナルチェーニング(ES2020: 推奨)
console.log(user?.address?.city); // null なら undefined を返す(エラーにならない)
// Null 合体演算子との組み合わせ
const city = user?.address?.city ?? "未設定";
パターン(4): querySelector の結果を未チェックで使用
NG
// 要素が存在しないページで実行するとエラー
document.querySelector(".special-banner").style.display = "none";
// .special-banner がないページ → querySelector は null → TypeError
OK: null チェック付き
// if 文
const banner = document.querySelector(".special-banner");
if (banner) {
banner.style.display = "none";
}
// オプショナルチェーニング
document.querySelector(".special-banner")?.style.display = "none"; // NG: 代入には使えない
// ↑ 代入の左辺にはオプショナルチェーニングは使えないため if 文を使う
オプショナルチェーニングは代入の左辺に使えない
el?.style.display = "none" は SyntaxError になります。代入を行う場合は if (el) { el.style.display = "none"; } と書いてください。?. は読み取り専用です。パターン(5): 動的に生成される要素を取得しようとした
NG
// Ajax で読み込まれる前に取得しようとする
const item = document.querySelector(".dynamic-item"); // null(まだ DOM にない)
item.addEventListener("click", handler); // TypeError!
OK: イベントデリゲーション
// 親要素(常に存在する)にイベントを登録
document.querySelector(".item-list").addEventListener("click", (e) => {
const item = e.target.closest(".dynamic-item");
if (item) {
handler(item);
}
});
動的要素にはイベントデリゲーションを使う
Ajax や SPA で後から追加される要素に直接イベントを登録することはできません。常に存在する親要素にイベントを登録し、
Ajax や SPA で後から追加される要素に直接イベントを登録することはできません。常に存在する親要素にイベントを登録し、
e.target.closest() でクリックされた要素を判定してください。オプショナルチェーニング(?.)の活用
JavaScript(?. の各パターン)
// プロパティアクセス const city = user?.address?.city; // user や address が null/undefined なら undefined // メソッド呼び出し const length = arr?.length; // arr が null なら undefined const upper = str?.toUpperCase?.(); // str や toUpperCase が null なら undefined // 配列アクセス const first = arr?.[0]; // arr が null なら undefined // Null 合体演算子との組み合わせ(デフォルト値) const name = user?.name ?? "ゲスト";
| 書き方 | 動作 |
|---|---|
| obj?.prop | obj が null/undefined なら undefined を返す |
| obj?.method() | obj が null/undefined なら undefined(メソッドは呼ばれない) |
| arr?.[index] | arr が null/undefined なら undefined |
| value ?? default | value が null/undefined なら default を返す |
デバッグの手順
| 手順 | 方法 |
|---|---|
| (1) エラーの行番号を確認 | コンソールのエラーメッセージで「at script.js:5」の 5 行目を見る |
| (2) null の変数を特定 | その行で .xxx にアクセスしている変数が null |
| (3) console.log で確認 | アクセスの直前に console.log(変数) を入れて null を確認 |
| (4) なぜ null かを調査 | DOM 未ロード / スペルミス / API レスポンス / 要素未存在のいずれか |
| (5) 解決策を適用 | defer / null チェック / ?. / イベントデリゲーション |
JavaScript(デバッグ用 console.log)
// エラーが出る行の直前にログを入れる
const el = document.getElementById("title");
console.log("el =", el); // null ならここで原因がわかる
el.textContent = "Hello"; // ← ここでエラーになっていた
エラーを未然に防ぐベストプラクティス
| 対策 | 方法 |
|---|---|
| スクリプトの実行タイミング | defer 属性を使う / DOMContentLoaded で囲む |
| DOM 取得後の null チェック | if (el) { ... } で囲む |
| API レスポンスの安全なアクセス | オプショナルチェーニング ?. を使う |
| 動的要素のイベント登録 | イベントデリゲーション(親要素に登録) |
| TypeScript の導入 | 型チェックで null アクセスをコンパイル時に検出 |
関連するエラー
| エラー | 原因 |
|---|---|
| Cannot read properties of null | 変数が null(値がない) |
| Cannot read properties of undefined | 変数が undefined(未定義 / 未初期化) |
| xxx is not a function | 変数が関数ではない(null/undefined や別の型) |
| Cannot set properties of null | null に対して値を代入しようとした |
Cannot read properties of undefined も原因と対策はほぼ同じです。null は「値がない」、undefined は「変数が未定義 / プロパティが存在しない」という違いがあります。
よくある質問
Qnull と undefined の違いは?
A
null は「意図的に値がない」ことを示します(例: getElementById で要素が見つからない → null を返す)。undefined は「変数が宣言されたが値が代入されていない」または「オブジェクトのプロパティが存在しない」場合に返されます。対策は同じ(null チェック / ?.)です。Qオプショナルチェーニング(?.)は全ブラウザで使えますか?
AES2020 の機能で、Chrome 80+ / Firefox 72+ / Safari 13.1+ / Edge 80+ で対応しています。IE 11 では使えません。IE 対応が必要な場合は
if (obj && obj.prop) と書いてください。QTypeScript を使えばこのエラーは起きませんか?
ATypeScript の
strictNullChecks を有効にすると、null/undefined の可能性がある変数へのアクセスをコンパイル時に検出できます。ただしランタイム(API レスポンス等)の null は型と実際の値が異なる場合があるため、完全には防げません。QquerySelectorAll は null を返しますか?
A
querySelectorAll は要素が見つからない場合でも空の NodeList(length=0)を返します。null にはなりません。一方、querySelector(単数)はnull を返します。QReact / Vue でもこのエラーは出ますか?
Aはい。特に
ref が null の状態でアクセスした場合や、API レスポンスの state が初期値(null)のままレンダリングされた場合に発生します。React なら {data && data.name} や {data?.name}、Vue なら v-if="data" で対処してください。Qconsole.log ではなくブレークポイントで調べるべきですか?
Aブラウザの開発者ツール(Sources タブ)でブレークポイントを設定すれば、実行を一時停止して変数の値を確認できます。
console.log より効率的ですが、慣れないうちは console.log でも十分です。まとめ
Cannot read properties of null の原因と対策をまとめます。
| 原因 | 対策 |
|---|---|
| DOM 未ロードで getElementById が null | defer 属性 / DOMContentLoaded / body 末尾に配置 |
| ID / クラス名のスペルミス | HTML の id / class とコードを照合。console.log で確認 |
| API レスポンスに null が含まれる | オプショナルチェーニング(?.)でアクセス |
| querySelector の結果を未チェックで使用 | if (el) { … } で null チェック |
| 動的生成要素を取得できない | イベントデリゲーション(親要素にイベント登録) |

