TypeScriptでフォームバリデーションエラーを扱う設計パターン!初心者向け例外処理ガイド
生徒
「TypeScriptでお問い合わせフォームなどを作るとき、入力ミスを上手に伝える方法はありますか?」
先生
「はい、バリデーションエラーを適切に扱う設計パターンがあります。エラーをただ出すだけでなく、整理して管理することが大切ですよ。」
生徒
「エラーを整理する……難しそうですね。プログラミングに詳しくなくても分かりますか?」
先生
「大丈夫です!身近な例えを使いながら、基本的な例外処理の仕組みから丁寧に解説していきますね。」
1. バリデーションエラーとは何か?
まずは、バリデーションエラーという言葉の意味から学んでいきましょう。バリデーションとは、日本語で「確認」や「検証」という意味です。例えば、あなたがウェブサイトの会員登録画面で、名前やメールアドレスを入力する場面を想像してください。
もしメールアドレスの欄に「あいうえお」と入力して送信ボタンを押したらどうなるでしょうか。システムは「これは正しいメールアドレスの形式ではありませんよ」と教えてくれますよね。このように、入力されたデータが正しいルールに従っているかをチェックし、不備があった場合に発生させるのがバリデーションエラーです。
TypeScriptを使うと、このチェック処理を非常に安全に、そして分かりやすく書くことができます。初心者の方が最初に覚えるべきは、変なデータが入力されたときに「それはダメですよ」と優しく教えてあげる仕組み作りなのです。
2. try-catch構文を使った例外処理の基本
プログラムの中でエラーが発生したとき、何も対策をしていないとアプリ全体が真っ白になって止まってしまいます。それを防ぐための道具がtry-catch(トライ・キャッチ)という構文です。
これは、「とりあえずこの処理をやってみて(try)、もし失敗したらエラーを捕まえて(catch)別のことをする」という仕組みです。落とし穴がある道を歩くときに、あらかじめ網を持って準備しておくようなイメージですね。バリデーションエラーも、この網で捕まえることで、画面にメッセージを出すなどの適切な対応ができるようになります。
function checkUserName(name: string) {
try {
if (name.length === 0) {
// わざとエラーを発生させる(投げる)
throw new Error("名前が入力されていません!");
}
console.log("名前は正常です:" + name);
} catch (error) {
// エラーを捕まえて表示する
console.log("エラーが発生しました:" + error.message);
}
}
checkUserName(""); // 名前が空なのでエラーになる
実行結果は以下のようになります。
エラーが発生しました:名前が入力されていません!
3. Errorクラスを継承して専用のエラーを作る
TypeScriptでは、ただのエラーではなく「これは入力ミス専用のエラーです」という特別な種類のエラーを自分で作ることができます。これを継承(けいしょう)と呼びます。元々あるErrorという仕組みをコピーして、自分流にカスタマイズするようなものです。
なぜこれが必要なのでしょうか。それは、通信エラーやシステム故障などの「深刻なエラー」と、ユーザーの入力ミスである「バリデーションエラー」を区別したいからです。区別ができれば、入力ミスの場合だけ赤い文字で画面にヒントを出す、といった親切な設計が可能になります。
// バリデーション専用のエラークラスを作る
class ValidationError extends Error {
constructor(message: string) {
super(message); // 元々のErrorの機能を使う
this.name = "ValidationError"; // このエラーに名前をつける
}
}
function validateAge(age: number) {
if (age < 0 || age > 150) {
throw new ValidationError("年齢は0から150の間で入力してください。");
}
console.log("年齢は適切です。");
}
4. 複数のエラーをまとめて扱う設計パターン
実際のフォームでは、名前もメールアドレスも電話番号も、一度に全部チェックしたいことがありますよね。一つエラーが見つかるたびに処理を止めるのではなく、全部の項目を調べて「ここが違いますよ」と一覧で出してあげると、ユーザーにとって非常に親切です。
このパターンでは、エラーを溜めておくための配列(リストのようなもの)を準備します。各項目を順番にチェックしていき、ダメな箇所があればその都度リストに追加していきます。最後にリストが空でなければ、まとめてエラーとして処理するのです。これは、学校の先生がテストの採点をして、間違っている箇所すべてにバツをつけてから返却するのと似ています。
interface FormErrors {
[key: string]: string;
}
function validateForm(data: { email: string, tel: string }) {
const errors: FormErrors = {};
// メールのチェック
if (!data.email.includes("@")) {
errors.email = "正しいメールアドレスを入力してください。";
}
// 電話番号のチェック
if (data.tel.length < 10) {
errors.tel = "電話番号が短すぎます。";
}
return errors;
}
const myData = { email: "test-example.com", tel: "123" };
const resultErrors = validateForm(myData);
if (Object.keys(resultErrors).length > 0) {
console.log("入力に不備があります:", resultErrors);
}
5. 型安全なエラーレスポンスの作り方
TypeScriptの最大の特徴は、データに「型(かた)」という名前のラベルを貼れることです。これにより、プログラムを書いている最中に「この変数はエラーが入っている可能性があるな」とパソコンが教えてくれるようになります。
バリデーションの結果を返すときに、「成功したときのデータ」か「失敗したときのエラー情報」のどちらか一方を必ず返す、というルールを作ることがあります。これをResult型(リザルトがた)などと呼ぶ設計パターンです。この方法を使うと、開発者がエラーの処理をうっかり忘れてしまうというミスを劇的に減らすことができます。パソコンが常に監視してくれているような安心感があります。
type ValidationResult =
| { success: true, value: string }
| { success: false, error: string };
function processInput(input: string): ValidationResult {
if (input.length < 5) {
return { success: false, error: "5文字以上で入力してください。" };
}
return { success: true, value: input };
}
const result = processInput("abc");
if (result.success) {
console.log("成功!データは:" + result.value);
} else {
console.log("失敗...理由は:" + result.error);
}
6. 非同期処理でのバリデーションとエラーハンドリング
最近のウェブサイトでは、入力した瞬間に「そのユーザー名は既に使われています」と表示されることがありますよね。これは、裏側でサーバーに問い合わせをしているため、少し時間がかかる処理(非同期処理)になります。
TypeScriptでこのような「待ち時間が発生する処理」のエラーを扱うには、asyncやawaitといった特別な呪文を使います。サーバーが混んでいて返事が来ない場合や、インターネットが切れてしまった場合など、入力ミス以外の原因でエラーが起きる可能性も高まります。そのため、ここではより慎重なエラーハンドリングが求められます。通信中のぐるぐる回るアイコンを出したり、やり直しボタンを表示したりといった工夫と組み合わせて使いましょう。
7. ユーザーに優しいエラーメッセージの表示方法
最後に、プログラミングの技術的なことだけでなく、使い勝手の面で大切なことをお伝えします。どれだけ完璧なエラーハンドリングを実装しても、表示されるメッセージが「システムエラー ID:500」のような暗号では、初心者のユーザーは困ってしまいます。
エラーメッセージを設計する際は、以下の3つのポイントを意識しましょう。
- 何が起きたのか(例:パスワードが短すぎます)
- なぜダメなのか(例:セキュリティ向上のため8文字以上必要です)
- どうすれば解決するのか(例:あと3文字追加してください)
これらをTypeScriptのコードの中で定義しておくことで、誰にでも使いやすい親切なシステムが出来上がります。バリデーションは、機械が人間を拒絶するためのものではなく、正しい操作へと導くための「道しるべ」なのです。この考え方を忘れずに、設計パターンを活用していきましょう。