5.5 例外処理
コンパイルエラーでは検知できない、実行時に起こるエラー(ランタイムエラー・例外)を取り扱うための構文です。
5.5.1 throw文とErrorオブジェクト
Section titled “5.5.1 throw文とErrorオブジェクト”エラーを意図的に発生させる(エラーを投げる)には、throw 文を使用します。
Errorオブジェクト: 通常はnew Error("エラーメッセージ")として作成したオブジェクトを投げます。- 挙動:
throw文が実行されると、そこでプログラムの実行が中断され、クラッシュ(強制終了)してエラーメッセージとスタックトレース(実行経路の履歴)が出力されます。
5.5.2 例外をキャッチするtry-catch文
Section titled “5.5.2 例外をキャッチするtry-catch文”例外によるプログラムのクラッシュを防ぎ、エラー処理を行うための構文です。
- 構文:
try { ... } catch (err) { ... } - 処理の流れ:
tryブロック内で例外が発生すると、即座に実行が中断され、catchブロックへ処理が移行します。try内で例外が起きなければcatchブロックは無視されます。 - エラーの受け取り:
catch (err)の変数errには、投げられたErrorオブジェクトが入ります。
5.5.3 例外処理と大域脱出
Section titled “5.5.3 例外処理と大域脱出”例外が持つ最大の特徴は、発生箇所から関数やブロックを無視して、呼び出し元の try-catch まで一気に制御を移す 大域脱出 にあります。
- メリット: 深い階層の関数でエラーが起きても、呼び出し元の大元で1箇所にまとめてエラー処理を記述できる点です。
- デメリットと型の問題:
catch (err)のerrは型が予測できないためunknown型となり、型システム上は少々扱いにくいという欠点があります。 - 設計の指針: 場合によってエラー処理を細かく変えたい場合は、例外を使わず、関数の返り値として失敗を表す値(
undefinedや独自のエラー型)を返すアプローチのほうが、TypeScriptの型システムと相性が良く安全です。
5.5.4 finallyで脱出に割り込む
Section titled “5.5.4 finallyで脱出に割り込む”try-catch の後に finally { ... } ブロックを追加することができます(catch を省略して try-finally とすることも可能)。
- 挙動: エラーが起きたかどうかにかかわらず、何が何でも必ず実行される ブロックです。
- 脱出への割り込み: 例外による大域脱出や、
return文による関数からの脱出が発生した際にも、その脱出に割り込んで必ずfinallyブロックが実行されます。ファイルのクローズなど、必ず行わなければならない事後処理(クリーンアップ)に最適です。
コラム25 throwは何でも投げられる
Section titled “コラム25 throwは何でも投げられる”throw 文は Error オブジェクトだけでなく、数値(throw 123;)や null など、どんな値でも投げることができます。
- カスタムエラー:
Errorクラスを継承してclass EmptyArrayError extends Errorのような独自のエラークラスを作ると、catch側でinstanceofを使って特定のエラーだけを処理しやすくなります。 - 特殊な用途: 最近のフロントエンド開発(ReactのSuspenseなど)では、大域脱出の性質を利用して「通信中の
Promiseオブジェクトをthrowする」というアグレッシブな手法も登場しています。