This article was translated from Japanese by AI and may contain inaccuracies. For the most accurate content, please refer to the original Japanese version.
クリームメロンソーダのイラスト

Error インスタンスかどうか判定する Error.isError() メソッド

Error.isError() メソッドは、オブジェクトが Error インスタンスかどうかを判定するためのメソッドです。今までも instanceof 演算子を使用して判定することができましたが、偽陽性と偽陰性が発生する可能性があります。Error.isError() メソッドは Array.isArray() と同じく内部スロットを使用して判定するため、より堅牢に判定することができます。

Error.isError() メソッドは、オブジェクトが Error インスタンスかどうかを判定するためのメソッドです。渡された値が Error インスタンスであれば true を、そうでなければ false を返します。

const error = new Error("An error occurred");
console.log(Error.isError(error)); // true
console.log(Error.isError({})); // false
console.log(Error.isError(3)); // false
console.log(Error.isError(null)); // false

Error.isError() メソッドの使い方

Error.isError() メソッドの使い道として真っ先に思いつくのは、try-catch 構文でキャッチしたエラーが Error インスタンスかどうかを判定することです。TypeScript では catch 節でキャッチしたエラーの型は unknown 型になります。これは JavaScript はどのような型の値でも例外としてスローできるためです。

適切なエラー処理を行うためには、キャッチしたエラーが Error インスタンスであるかどうかを判定する必要があります。Error.isError() メソッドを使用することで、簡単に判定できます。

try {
  // 何らかの処理
} catch (error) {
  if (Error.isError(error)) {
    console.error(error.message);
  } else {
    console.error("Unknown error:", error);
  }
}

とはいえ、この用途であれば Error.isError() メソッドを使用しなくても、instanceof 演算子を使用して判定することもできます。

try {
  // 何らかの処理
} catch (error) {
  if (error instanceof Error) {
    console.error(error.message);
  } else {
    console.error("Unknown error:", error);
  }
}

しかし、instanceof 演算子を使用した判定では偽陽性と偽陰性が発生する可能性があります。たとえば、以下のように __proto__ プロパティを無理やり上書きしてしまえば、本物の Error インスタンスでない場合でも instanceof 演算子は true を返してしまいます。

const error = new Error("An error occurred");
const fakeError = {
  message: "Fake error",
  __proto__: Error.prototype,
};
 
console.log(error instanceof Error); // true
console.log(fakeError instanceof Error); // true

Error.isError() メソッドを使用するとプロトタイプチェーン内で Error であったとしても Error インスタンスでない場合は false を返します。これにより、偽陽性を防ぐことができます。

const error = new Error("An error occurred");
const fakeError = {
  message: "Fake error",
  __proto__: Error.prototype,
};
console.log(Error.isError(error)); // true
console.log(Error.isError(fakeError)); // false

この挙動は Array.isArray() と同じ仕組みによって実現されています。Array.isArray()Error.isError() メソッドは偽装不可能な内部スロット([[Internal Slot]])を直接チェックして真偽値を返します。このような内部スロットの有無の確認は「ブランドチェック」と呼ばれています。

cross-realm 環境での使用

Error.isError() メソッドは cross-realm 環境で偽陽性を防ぐために使用できます。たとえば、iframeWeb Worker などの異なる実行環境で Error インスタンスを作成した場合、instanceof 演算子は常に false を返します。

Error.isError() メソッドを使用することで、異なる実行環境で作成された Error インスタンスでも正しく判定できます。

const iframe = document.createElement("iframe");
document.body.appendChild(iframe);
const iframeError = iframe.contentWindow?.Error;
const error = new iframeError("An error occurred");
 
console.log(error instanceof Error); // false
console.log(error instanceof iframeError); // true
console.log(Error.isError(error)); // true

まとめ

  • Error.isError() メソッドは、オブジェクトが Error インスタンスかどうかを判定するためのメソッド
  • instanceof 演算子を使用した Error インスタンスの判定では偽陽性と偽陰性が発生する可能性がある
  • Error.isError() メソッドは Array.isArray() と同じく内部スロットを使用して判定するため、偽陽性や偽陰性を防ぐことができる
  • cross-realm 環境で作成された Error インスタンスでも正しく判定できる

参考

Comprehension check

Answer the following questions to deepen your understanding of the article.

`instanceof` 演算子を使用して `Error` インスタンスを判定する際の問題点は何ですか?

  • 偽陽性と偽陰性が発生する可能性がある

    Correct!

    Error インスタンスでない場合でも、__proto__ プロパティを上書きしてしまうと `instanceof` 演算子は `true` を返してしまいます。

  • パフォーマンスが悪い

    Try again

  • TypeScript では型ガードとして機能しない

    Try again

  • ブラウザの互換性の問題がある

    Try again