メソッドの存在チェックはtypeof !== "undefined"じゃ足りない

  • TypeScript
  • JavaScript

この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。

インターフェースにオプショナルなメソッドがある場合、呼び出し前に存在チェックを入れることがある。そのチェックの書き方を3パターン見比べてみた。

3パターン

if (typeof me.onChange !== "undefined") {
// safe to use the function
}
if (typeof me.onChange === "function") {
// safe to use the function
}
if (typeof me.onChange !== "undefined" && typeof me.onChange === "function") {
}

それぞれの中身

1つ目の!== "undefined"は「未定義ではない」ことしか見ていない。onChangeに文字列や数値が入っていても真になるので、その中でme.onChange()を呼ぶとTypeError: onChange is not a functionになり得る。コメントの「safe to use the function」は成立しない。

2つ目の=== "function"は、typeofが"function"を返すのが実際に呼び出し可能な値のときだけなので、この分岐の中で呼んでも安全になる。

3つ目は&&で両方を繋いでいるが、typeof x === "function"が真なら自動的にtypeof x !== "undefined"も真になるので、前半の条件は冗長。2つ目と実質同じ。

結論

存在チェックとして意味があるのはtypeof x === "function"だけ。!== "undefined"は型を保証しないので、関数呼び出しの安全性チェックとしては使えない。

TypeScriptなら呼び出し側はoptional chainingで書ける。

me.onChange?.();

これは内部的に呼び出し可能性のチェックをして、undefined/nullなら何もしない。ただし関数以外の値が入っているケースまでは救えないので、根本対応としてはonChange?: () => voidのようにオプショナルなメソッド型として宣言しておく方がいい。