皆さん、こんにちは! TypeScriptの海へようこそ!
TypeScript、触り始めたばかりですか? それとも、そろそろ「もう一歩踏み込んで、もっと賢くコードを書きたいな」なんて思い始めていますか? 素晴らしいですね!
開発の世界に身を置いていると、切っても切り離せないもの、それが「エラー」です。完璧なコードなんて、夢のまた夢。どんなベテランだって、予期せぬエラーに遭遇することは日常茶飯事。だからこそ、エラーをどう「処理」するかが、本当に大事なんです。
今日は、そんなエラー処理の中でも、特に「`try-catch` の `catch` 節で捕まえるエラー変数の型」について、皆さんのコードを一段も二段も安全にしてくれる、とっておきの設定をご紹介します。その名も「`useUnknownInCatchVariables`」!
なんだか難しそうな名前だなって思いました? 大丈夫ですよ。この記事を読み終える頃には、「なるほど!これは設定するしかない!」と、きっと膝を打つはずです。
—
😱 エラーって、どうやって捕まえるの? — `try-catch` のおさらい
まずは、エラーを捕まえる基本的な仕組み「`try-catch`」について、サラッとおさらいしましょう。これは、まるで「お料理」と「ハプニング」の関係に似ています。
あなたがレシピ通りに美味しい料理を作ろうとしているとします。
- `try` ブロック:
「このレシピ通りに作ってみるぞ!」という、実際に料理を作る部分です。ここには、成功してほしい処理を書きます。
- `catch` ブロック:
「もし、途中で材料が焦げ付いちゃったり、調味料を入れ間違えちゃったりしたらどうする?」という、万が一の失敗(エラー)を想定して、どう対処するかを書く部分です。
例えば、こんな感じ。
try {
// ここで難しい計算をしたり、外部のサービスからデータを取ってきたりするイメージ
// もし、うまくいかなかったら、エラーが発生するかもしれない!
const result = someRiskyOperation(); // 危険な操作を実行する関数
console.log(“計算結果:”, result);
} catch (error) { // もしエラーが起こったら、そのエラーの情報がこの ‘error’ 変数に入ります
// エラーが起こったときの対処法をここに書く
console.error(“大変!エラーが発生しました:”, error);
}
この `catch (error)` の `error` 変数。これこそが、今日の主役なんです!
—
📦 昔の `error` 変数は「なんでもアリ」な `any` だった…(ちょっと怖い話)
TypeScriptに触れたばかりの皆さんは、おそらく「型」のありがたみを日々感じていることでしょう。コードに「これは文字列だよ」「これは数字だよ」って教えてあげると、TypeScriptが「うんうん、ちゃんと使ってるね!」ってチェックしてくれる。もし間違っていたら、「あれ?型が違うよ!」って、優しく教えてくれる。
でも、昔の `catch` 節の `error` 変数は、ちょっと違いました。デフォルトでは、その型がなんと「`any`」だったんです!
`any` 型、ご存知ですか? これは「なんでもアリ」の魔法の箱みたいなものです。どんなものでも入るし、どんなものとして取り出そうとしても、TypeScriptは何も文句を言いません。
try {
throw new Error(“意図的にエラーを発生させます!”);
} catch (error) { // この ‘error’ は、デフォルトだと any 型として扱われていました
console.log(error.message); // エラーオブジェクトの message プロパティにアクセス
console.log(error.statusCode); // 存在しないかもしれない statusCode プロパティにもアクセスできちゃう!
// TypeScriptは何も警告してくれない…😱
}
これが、なぜ問題だったのか?
想像してみてください。あなたは「これは絶対にエラーオブジェクト (`Error` クラスのインスタンス) だ!」と思って `error.message` にアクセスしました。でも、もし実際に飛んできたエラーが、ただの文字列 `”接続エラー”` だったり、はたまた `undefined` だったりしたらどうなるでしょう?
`”接続エラー”.message` は `undefined` ですし、`undefined.message` なんて実行したら、プログラムは即座に停止してしまいます (`TypeError: Cannot read properties of undefined (reading ‘message’)` のようなエラーが発生)。
TypeScriptは、この `any` のせいで、エラー処理の肝心な部分で「見て見ぬふり」をしてしまっていたんです。これは、現場では本当に痛い目に遭うことが多かったんです。せっかくTypeScriptを使っているのに、一番守ってほしいところで守ってくれないなんて…ね?
—
✨ 救世主登場! `unknown` 型と `useUnknownInCatchVariables` オプション
そこで登場するのが、今日の主役「`unknown` 型」と、それを有効にする `tsconfig.json` の設定「`useUnknownInCatchVariables`」です!
`unknown` 型って、どんな型?
`unknown` 型も、`any` と同じく「なんでも入る魔法の箱」です。数字、文字列、オブジェクト、何でも受け入れます。
でも、ここが `any` との決定的な違い!
`unknown` 型の箱から何かを取り出すときは、「これって、何が入ってるの? ちゃんと確認してから使ってね!」と、TypeScriptが厳しくチェックしてくれるんです。
例えるなら、`any` が「中身が何でもOKで、確認なしで取り出せる、ちょっと危険な箱」なら、
`unknown` は「中身が何でもOKだけど、取り出す前に必ず『中身の検査』が必要な、とっても安全な箱」といったイメージです。
設定してみよう! `useUnknownInCatchVariables: true`
この賢い `unknown` 型を、`catch` 節の `error` 変数に適用してくれるのが、`tsconfig.json` の `useUnknownInCatchVariables` オプションです。
`tsconfig.json` は、TypeScriptのプロジェクトの設定ファイルですね。この中の `compilerOptions` に、以下の行を追加するだけです。
// tsconfig.json
{
“compilerOptions”: {
// 他のいろんな設定がここにあると思います
“target”: “es2020”,
“module”: “commonjs”,
“strict”: true, // strictモードはぜひ有効にしておきましょう!
// 👇 これを追加するだけ!
“useUnknownInCatchVariables”: true
},
“include”: [
“src//”
]
}
この設定を `true` にすると、以降のプロジェクト内の `catch (error)` の `error` 変数は、自動的に `unknown` 型として扱われるようになります。
—
🕵️♀️ `unknown` 型を安全に使うための「型ガード」
さて、`error` が `unknown` 型になったのは良いとして、「じゃあ、どうやって使うの?」ってなりますよね。
`unknown` は「中身の検査」が必要でした。この「検査」のことを、TypeScriptの世界では「型ガード (Type Guard)」と呼びます。
具体例を見てみましょう。
try {
// 例えば、JSON文字列をパースしようとして、不正な形式だった場合にエラーが発生するケース
const jsonData = JSON.parse(“これはJSONじゃないよ”); // エラーを発生させる!
console.log(jsonData);
} catch (error) { // ✨ この error は unknown 型になります!
// そのままでは error.message にアクセスできません!
// console.error(error.message); // 🚨 TypeScriptがエラーを報告します!
// ‘error’ is of type ‘unknown’.
// ここで「型ガード」の出番です!
// 1. もし、エラーが Error クラスのインスタンスだったら?
if (error instanceof Error) {
// このブロックの中では、error は Error 型として扱われます。
// だから、安全に error.message にアクセスできます!
console.error(“キャッチされたエラー (Error型):”, error.message);
console.error(“スタックトレース:”, error.stack);
}
// 2. もし、エラーがただの文字列だったら?
else if (typeof error === ‘string’) {
// このブロックの中では、error は string 型として扱われます。
console.error(“キャッチされたエラー (string型):”, error);
}
// 3. その他の未知のタイプだったら?
else {
// 何が起こったか分からないけど、とりあえずログに出しておく
console.error(“キャッチされた不明なエラー:”, error);
// あるいは、JSON.stringify で内容を文字列化して表示する
console.error(“詳細:”, JSON.stringify(error, null, 2));
}
}
どうですか? ちょっとコードが増えましたが、これで「もしエラーが `Error` 型だったらこうする」「もし文字列だったらこうする」と、エラーの種類に応じて、適切に処理を分岐できるようになりました。
一見すると「面倒くさいな」と感じるかもしれません。でも、このひと手間が、未来の自分やチームを、思わぬバグから救うことになるんです。泥臭いけれど、これこそが堅牢なシステムを作るための大切なステップなんですよ!
—
🚀 なぜ `unknown` がそんなに素晴らしいの? — 現場のリアルなメリット
`useUnknownInCatchVariables: true` を設定し、`unknown` 型としてエラーを扱うことには、こんなにたくさんのメリットがあります。
1.
🐛 バグの早期発見・防止
`any` のままでは気づかなかった、「エラー変数が期待と違う型だった」というバグを、コードを実行する前にTypeScriptが教えてくれるようになります。開発の早い段階でバグを見つけられるのは、本当に大きいんです。
2.
🛡️ コードの堅牢性(壊れにくさ)が格段に向上
予期せぬエラーの種類が飛んできたときに、安易にプロパティにアクセスしてプログラムがクラッシュする、なんて事態を防げます。これにより、アプリケーションがより安定して動作するようになります。
3.
🤝 コードの可読性・保守性の向上
エラー処理の部分を見れば、「このエラーはどんな種類を想定しているのか」「どういう場合にどう処理するのか」が明確になります。これは、チーム開発や、将来の自分がコードを修正するときに、大きな助けになります。
4.
🌟 TypeScriptの恩恵を最大限に享受
せっかくTypeScriptを使っているのに、エラー処理の部分だけ `any` で型チェックをすり抜けるのはもったいないですよね。この設定を有効にすることで、TypeScriptの強力な型チェックを、コードの隅々まで行き渡らせることができます。
—
🤔 よくある疑問、ちょっとだけフォロー
- 「なんでデフォルトで `unknown` じゃなかったの?」
これはTypeScriptの歴史的な経緯が関係しています。昔からJavaScriptには `try-catch` があり、その `catch` 変数には何でも入りました。TypeScriptが生まれた当初、既存のJavaScriptコードとの互換性を保つため、`any` がデフォルトになっていました。しかし、安全性の観点から `unknown` の方が望ましいという声が多くなり、このオプションが導入されたんです。
- 「結局 `any` でも動くんだし、この設定いらないんじゃない?」
確かに「動かすだけ」なら `any` でも動きます。でも、それは例えるなら「ブレーキが効くかどうかわからない車に乗る」ようなものです。今は大丈夫でも、いつ事故を起こすかわかりません。TypeScriptは、そんな危険を未然に防ぐための「安全装置」なんです。ぜひ、その安全装置をONにしてあげてください。
- 「いちいち型ガード書くのが面倒くさい…」
わかります、その気持ち! コード量が増えるのは少し抵抗がありますよね。でも、それはまさに「安全への投資」です。この一手間が、後々のデバッグ時間や、予期せぬ障害対応のコストを大幅に削減してくれるはずです。長い目で見れば、圧倒的に効率が良い選択なんですよ。
—
🙌 まとめ:小さな設定が、大きな安全と安心をくれる
今日は、`tsconfig.json` の `useUnknownInCatchVariables` オプションについて、じっくりと見てきました。
- `catch` 節の `error` 変数は、デフォルトだと「なんでもアリ」な `any` でした。
- `useUnknownInCatchVariables: true` を設定すると、`error` 変数が「必ず検査が必要」な `unknown` 型になります。
- `unknown` 型の変数は、`instanceof` や `typeof` といった「型ガード」を使って、安全に中身を検査してから利用します。
- この設定は、バグの早期発見、コードの堅牢性向上、そして何より「安心してコードを書ける」という大きなメリットをもたらしてくれます。
TypeScriptは、皆さんの開発をよりスムーズに、より安全に進めるための強力な味方です。この `useUnknownInCatchVariables` も、そんなTypeScriptの優しさが詰まった設定の一つ。
「よし、ちょっとだけ手間はかかるけど、未来の自分のためにやってみるか!」
そう思っていただけたら、私は最高に嬉しいです。小さな一歩が、皆さんの開発体験を大きく変えてくれるはず。ぜひ、今日からこの設定を試してみてくださいね!
それでは、また次回のTypeScriptのお話で!

コメント