TypeScriptのtry/catchでエラーハンドリング!例外処理の基本を初心者向けに解説
生徒
「TypeScriptでプログラムを書いているとき、途中でエラーが起きて止まってしまうのが怖いのですが、何か対策はありますか?」
先生
「それはとても大切な視点ですね。プログラムには予期せぬトラブルがつきものですが、try/catch文を使うことで、エラーを優しく受け止めて処理を続けることができるんですよ。」
生徒
「例外処理っていう言葉を聞いたことがありますが、それのことでしょうか?」
先生
「その通りです!例外処理をマスターすれば、アプリが突然真っ白になったり動かなくなったりするのを防げます。具体的な使い方を一緒に見ていきましょう!」
1. エラーハンドリングと例外処理とは?
プログラミングの世界では、どれだけ完璧にコードを書いたつもりでも、エラーが発生することがあります。例えば、インターネットの接続が突然切れてしまったり、入力されるはずのない文字が入力されたりする場合です。これを例外と呼びます。
エラーハンドリングとは、このような予期せぬトラブルが発生したときに、プログラムが強制終了しないように、あらかじめ対策を立てておくことを指します。TypeScriptでは主にtry...catchという仕組みを使って、この例外処理を行います。
もし例外処理を行っていないと、エラーが起きた瞬間にプログラムは動かなくなり、利用者は困ってしまいます。料理に例えるなら、塩を入れすぎてしまったときに、料理を全部捨てるのではなく、砂糖を入れて味を整えたり、スープを足したりしてリカバリーをする作業に似ています。
2. try/catch文の基本的な書き方
まずは一番シンプルな構造を覚えましょう。tryブロックの中に「エラーが起きるかもしれない処理」を書き、catchブロックの中に「エラーが起きたときに実行したい処理」を書きます。
以下のコードは、エラーが発生したときにメッセージを表示する例です。
try {
// ここに実行したいコードを書く
console.log("処理を開始します");
// 意図的にエラーを発生させてみます
throw new Error("トラブルが発生しました!");
console.log("この行は実行されません");
} catch (error) {
// エラーが起きたときにここに来る
console.log("エラーをキャッチしました");
console.log(error.message);
}
実行結果は以下のようになります。
処理を開始します
エラーをキャッチしました
トラブルが発生しました!
ここで登場したthrowというのは、「エラーを投げ飛ばす」という意味の命令です。エラーが投げられると、その後の処理は飛ばされて、すぐにcatchの中へと移動します。これが例外処理の基本的な流れです。
3. エラーの内容を確認する変数errorの役割
catch(error)のカッコの中にあるerrorという文字は、発生したエラーの情報を詰め込むための箱(変数)です。この箱の中には、何が原因でエラーになったのかという情報が入っています。
TypeScriptでは、このerrorの中身が何であるかを特定することが推奨されます。なぜなら、エラーには「通信エラー」や「計算エラー」など、たくさんの種類があるからです。初心者のうちは、まずはerror.messageを見ることで、エラーの内容を文字で確認できると覚えておけば十分です。
パソコンを触ったことがない方にとって、変数という言葉は難しいかもしれませんが、「エラーの内容が書かれたお手紙」が入っている封筒だとイメージしてみてください。catchはその封筒を受け取って、中身を確認する場所なのです。
4. 実践的な使い方:数値の計算チェック
次に、もう少し実用的な例を見てみましょう。例えば、割り算を行うプログラムで、0で割ろうとしたときにエラーを出す仕組みを作ってみます。数学では0で割ることはできないため、プログラミングでも注意が必要なポイントです。
function divide(a: number, b: number) {
try {
if (b === 0) {
throw new Error("0で割ることはできません");
}
let result = a / b;
console.log("計算結果は " + result + " です");
} catch (e) {
console.log("計算エラーが発生しました");
console.log("理由:" + e.message);
}
}
divide(10, 2); // 正常なケース
divide(10, 0); // エラーになるケース
実行結果は以下のようになります。
計算結果は 5 です
計算エラーが発生しました
理由:0で割ることはできません
このように、あらかじめ条件を決めて自分でエラーを投げる(throwする)ことで、不正な操作を防ぐことができます。これはユーザーが間違った数値を入力したときなどに非常に役立ちます。
5. finallyブロック:必ず実行したい処理
tryとcatchに加えて、もう一つ重要なのがfinally(ファイナリー)ブロックです。これは、エラーが起きても起きなくても、最後に必ず実行される処理を書く場所です。
例えば、ファイルの編集を開いた後、エラーが起きても起きなくても最後には必ずファイルを閉じなければなりません。そういった「後片付け」に最適です。
function openFile() {
console.log("ファイルを開きます");
try {
console.log("データを読み込み中...");
// ここでエラーが起きたと想定
throw new Error("ファイルが壊れています");
} catch (error) {
console.log("エラー対応中:" + error.message);
} finally {
console.log("最後に必ずファイルを閉じます");
}
}
openFile();
実行結果は以下のようになります。
ファイルを開きます
データを読み込み中...
エラー対応中:ファイルが壊れています
最後に必ずファイルを閉じます
もしエラーが起きなかったとしても、最後に必ず「ファイルを閉じます」というメッセージが表示されます。これで、やり残しを防ぐことができるのです。
6. TypeScriptでの型安全なエラーハンドリング
TypeScriptを使う大きなメリットは、データの種類(型)を厳しくチェックできることです。しかし、実はcatchで受け取るエラーの型は、標準ではunknown(何かわからないもの)という扱いになります。これは、エラーの中身が文字列だったり数字だったり、あるいは特別なオブジェクトだったりする可能性があるからです。
より安全にコードを書くためには、以下のように「もしこのエラーがErrorという種類のものだったら」という確認を行うのが一般的です。これを専門用語で型ガードと呼びますが、今は「種類をチェックしているんだな」くらいの理解で大丈夫です。
try {
// 何らかの処理
let user = null;
console.log(user.name); // ここでエラーが発生
} catch (error: unknown) {
if (error instanceof Error) {
// ここではerrorが一般的なエラーだと確定している
console.log("標準的なエラーです:" + error.message);
} else {
console.log("不明なエラーが発生しました");
}
}
このように書くことで、TypeScriptはより安全に、そして確実にエラーの内容を扱えるようになります。初心者の方は、まずは基本のtry/catchを使いこなし、慣れてきたらこの「型」を意識した書き方に挑戦してみてください。
7. エラーを防ぐための考え方とコツ
最後に、エラーハンドリングを上手に行うためのコツをお伝えします。一番大切なのは、エラーを無視しないことです。catchブロックを空っぽにしてしまうと、エラーが起きているのにプログラムが何事もなかったかのように進んでしまい、後からもっと大きな問題に発展することがあります。
また、すべての処理を一つの巨大なtryで囲むのではなく、エラーが起きそうな場所をピンポイントで囲むようにしましょう。これにより、どこで問題が発生したのかがすぐに特定できるようになります。
パソコン操作に慣れていない方は、まずは文字を表示させるだけの簡単なプログラムから始めて、わざと間違った数値を入力してエラーを「わざと起こして」みてください。エラーと仲良くなることが、プログラミング上達への一番の近道です。TypeScriptが優しく教えてくれるエラーメッセージを読み解きながら、一歩ずつ進んでいきましょう。