エラノート エラノート

JavaScript TypeErrorの原因と解決法まとめ

JavaScript TypeError エラー解決 デバッグ
広告スペース (article-top)

JavaScriptのTypeError(型エラー)は、値に対して不適切な操作を行ったときに発生するエラーです。「Cannot read properties of null」や「is not a function」など、さまざまなメッセージで表示されます。この記事では頻出パターンと対処法を解説します。

TypeErrorとは

TypeErrorは、ある値に対してその型では実行できない操作をしようとしたときに発生します。

null.toString();
// TypeError: Cannot read properties of null (reading 'toString')

undefined();
// TypeError: undefined is not a function

const num = 42;
num();
// TypeError: num is not a function

エラーメッセージにはどんな操作がなぜ失敗したかが書かれているので、まずはメッセージを正確に読むことが大切です。

パターン1: nullやundefinedのプロパティアクセス

最も多いTypeErrorのパターンです。

// NG: nullのプロパティにアクセス
const element = document.querySelector("#nonexistent");
console.log(element.textContent);
// TypeError: Cannot read properties of null (reading 'textContent')

document.querySelectorは要素が見つからないとnullを返します。nullにはプロパティがないためエラーになります。

解決方法

// 方法1: nullチェック
const element = document.querySelector("#myElement");
if (element !== null) {
  console.log(element.textContent);
}

// 方法2: オプショナルチェーン
const element = document.querySelector("#myElement");
console.log(element?.textContent);  // nullなら undefined が返る

// 方法3: 要素の存在を前提としない設計
const element = document.querySelector("#myElement");
if (element) {
  element.addEventListener("click", handleClick);
} else {
  console.warn("要素 #myElement が見つかりません");
}

パターン2: 「is not a function」エラー

関数ではないものを関数として呼び出そうとするとエラーになります。

// NG: 変数を関数のように呼び出す
const name = "太郎";
name();
// TypeError: name is not a function

// NG: プロパティ名のスペルミス
const arr = [1, 2, 3];
arr.lenght;  // undefined(スペルミス)
// arr.lenght(); とするとTypeError

解決方法

// メソッド名のスペルを確認する
const arr = [1, 2, 3];
console.log(arr.length);   // 3(プロパティ、カッコ不要)
console.log(arr.includes(2));  // true(メソッド、カッコ必要)
// コールバック関数が正しく渡されているか確認
function processData(data, callback) {
  // callbackが関数かどうか確認
  if (typeof callback === "function") {
    callback(data);
  }
}

processData("test", null);  // エラーにならない
processData("test", (d) => console.log(d));  // "test"

パターン3: 配列メソッドの誤用

配列でないものに配列メソッドを使おうとするとエラーになります。

// NG: 文字列にpushは使えない
let text = "hello";
text.push(" world");
// TypeError: text.push is not a function

// NG: オブジェクトにmapは使えない
const user = { name: "太郎", age: 25 };
user.map((item) => item);
// TypeError: user.map is not a function

解決方法

// 文字列の結合
let text = "hello";
text = text + " world";  // 文字列結合
// または
text += " world";

// オブジェクトのキーや値をループ
const user = { name: "太郎", age: 25 };

// キーでループ
Object.keys(user).forEach((key) => {
  console.log(`${key}: ${user[key]}`);
});

// 値でループ
Object.values(user).forEach((value) => {
  console.log(value);
});

// エントリでループ
Object.entries(user).forEach(([key, value]) => {
  console.log(`${key}: ${value}`);
});

パターン4: const変数への再代入

// NG: constで宣言した変数に再代入
const MAX_SIZE = 100;
MAX_SIZE = 200;
// TypeError: Assignment to constant variable.

// OK: letで宣言する
let currentSize = 100;
currentSize = 200;

注意点として、constで宣言したオブジェクトや配列は、中身の変更は可能です。

const user = { name: "太郎" };
user.name = "花子";        // OK: プロパティの変更は可能
user.age = 25;             // OK: プロパティの追加も可能
// user = { name: "次郎" }; // NG: オブジェクト自体の再代入は不可

const arr = [1, 2, 3];
arr.push(4);    // OK: 要素の追加は可能
arr[0] = 10;    // OK: 要素の変更は可能
// arr = [5, 6]; // NG: 配列自体の再代入は不可

パターン5: JSON.parseのエラー

不正なJSON文字列をパースしようとするとエラーになります。

// NG: 不正なJSON
JSON.parse("hello");
// SyntaxError: Unexpected token 'h'

JSON.parse(undefined);
// SyntaxError: Unexpected token 'u'

// OK: 正しいJSON文字列
const data = JSON.parse('{"name": "太郎", "age": 25}');
console.log(data.name);  // "太郎"

解決方法: try-catchで安全にパース

function safeJsonParse(text) {
  try {
    return JSON.parse(text);
  } catch (error) {
    console.error("JSONのパースに失敗:", error.message);
    return null;
  }
}

const result = safeJsonParse('{"valid": true}');
console.log(result);  // { valid: true }

const invalid = safeJsonParse("not json");
console.log(invalid);  // null

デバッグのコツ

TypeErrorに遭遇したら、以下の手順で調査しましょう。

// 1. エラーメッセージを正確に読む
// "Cannot read properties of undefined (reading 'name')"
// → undefinedの'name'プロパティを読もうとしている

// 2. console.logで値を確認
const data = getData();
console.log("data:", data);         // 値の確認
console.log("type:", typeof data);  // 型の確認

// 3. スタックトレースを確認
// エラーメッセージの下に表示される呼び出し履歴を辿る

// 4. 型を意識した防御的プログラミング
function processItems(items) {
  if (!Array.isArray(items)) {
    console.error("itemsは配列である必要があります");
    return [];
  }
  return items.map((item) => item.toUpperCase());
}

TypeErrorは「期待した型と実際の型が違う」ことで発生します。変数の中身が想定通りかどうかをconsole.logtypeofで確認する癖をつけましょう。特にAPIから受け取ったデータやDOM操作の戻り値は、想定外の値が入っていることが多いため注意が必要です。

広告スペース (article-bottom)

あわせて読みたい