りゅうじの学習blog

学習したことをアウトプットしていきます。

4/25 TypeScript try-catch構文のcatchの引数の型

前提

  • tsconfig.jsonの設定でuseUnknownInCatchVariablesがtrueである(strictモードがtrueであればこの設定がtrueになるので同義です)

なぜ必要な知識か

  • catch (err) の errの型は設定がtrueであれば、unknownになり、falseであれば、any になる
  • unknownであった場合に、通常の書き方ではコンパイルエラーとなるのを解決するため

なぜそんな仕様になっているか

  • 型がErrorオブジェクトの型ではなくunknown, any型になるのは、JavaScriptの仕様上どんな値がthrowされるか分からないためです。
  • throwはなんでも投げられる、つまり、unknown, any型になります。

例えば

try {
throwNull ();
} catch (err) {
  console.log(err, "が投げられた");
}

function throwNull() {
  throw null;
}

実行結果

[LOG]: null,  "が投げられた"
  • なんでも投げられるので、今回はnullとしましたが、プリミティブ型のものでも投げられます
  • 冒頭の設定で、falseならany型になるのでコンパイルエラーにはなりませんが、trueですとunknown型なのでコンパイルエラーになります。

対処法

➀ Errorオブジェクトかどうかの条件分岐をする

② 明示的にany型にしてしまう

try {
    // なんらかの処理
  } catch (err) {
    if (err instanceof Error) {
      res.status(500).json({ message: err.message });
    } else {
      res.status(500).json("エラーオブジェクトでないエラーを受け取りました");
    }
  • catchの中でinstanceofを使い、Errorのインスタンスであるかどうかで条件分岐をしている

try {
    // なんらかの処理
  } catch (err: any) {
      res.status(500).json({ message: err.message });
  }

strictモードをtrueにしてやっているのなら、➀を使った方がいいのかなと思いました。

参考

サバイバルTypeScript

プロを目指す人のためのTypeScript入門