Programmingバックエンド開発者

TypeScriptにおけるカスタムエラーのメカニズムはどのように機能しますか?カスタムエラークラスを正しく宣言する方法、その型を指定する理由、'instanceof'やエラーのシリアル化に関する罠を避ける方法について説明してください。

Hintsage AIアシスタントで面接を突破

回答。

問題の歴史:JavaScriptでは、標準のエラーはErrorクラスで記述されています。大規模なTypeScriptプロジェクトでは、状況を正確に処理するために自分自身のエラー階層を使用することが重要ですが、型、継承、および'instanceof'の動作に関しては注意が必要です。

問題:Errorから継承する際に問題が発生する可能性があります。プロトタイプが失われ、'instanceof'が正しく機能せず、型が正確に記述されていない可能性があり、シリアル化はしばしばスタックトレースを失います。プロパティを明示的に指定しない場合、エラー処理でバグが発生する可能性があります。

解決策:Errorクラスを拡張してカスタムエラーを正しく定義します。名前を明示的に記述し、プロトタイプを手動で復元する必要があります(ES5やCommonJSへのコンパイル時に重要です)およびエラーフィールドの型を指定します。

コード例:

class ValidationError extends Error { code: number; constructor(message: string, code: number = 400) { super(message); Object.setPrototypeOf(this, ValidationError.prototype); this.name = 'ValidationError'; this.code = code; } } function process(user: string) { if (!user) throw new ValidationError('User required', 401); }

主な特徴:

  • トランスパイル後でも'instanceof'をサポートするための明示的なプロトタイプの復元。
  • カスタムエラープロパティの型指定。
  • 各論理エラーグループのための個別のクラス。

トリックのある質問。

Object.setPrototypeOf(this, ...)の呼び出しを省略できない理由は?

Object.setPrototypeOf(this, Class.prototype)を呼び出さなければならないのは、'instanceof' ValidationErrorがES5/CommonJSやBabelにコンパイルされた場合に機能しなくなるためです。これにより、catchブロックがValidationErrorをキャッチできなくなります。

class CustomErr extends Error {} const err = new CustomErr('msg'); console.log(err instanceof CustomErr); // setPrototypeOfなしではfalse

カスタムエラーのnameフィールドを省略しても良いか?

this.nameプロパティを設定しなければ、エラーのスタックとログ表示が不正確になり、原因とエラーの分類が難しくなります。

エラーをシリアライズ可能にする必要があるか?もしそうなら、どのように?

エラーは正しくシリアル化されるべきです(例:ロギングやネットワーク経由での送信のため)、さもなければJSON.stringify(new Error())はmessageやstackを出力しません。toJSONメソッドをオーバーライドする必要があります。

class SerializableError extends Error { toJSON() { return { name: this.name, message: this.message, stack: this.stack }; } }

タイプ定義エラーとアンチパターン

  • Object.setPrototypeOfの欠如により、instanceofが正しく機能しない
  • name及びカスタムプロパティの無視
  • toJSONが実装されていないエラーのシリアル化:stack/messageが失われる

実生活の例

ネガティブケース

プロジェクトでは、単にclass MyError extends Errorを行い、プロトタイプを復元せずにやっていました。エラーはif (err instanceof MyError)でキャッチされましたが、これは機能せず、コードはクリティカルな状況の処理をサイレントにスキップしました。

利点:

  • コードは簡潔でした
  • ボイラープレートがありませんでした

欠点:

  • instanceofは機能しませんでした
  • 例外が正しくログ記録されませんでした
  • ts->jsトランスパイラーの変更に伴う互換性の問題が発生しました

ポジティブケース

正しいCustomErrorを実装し、name、code、toJSONを明示的に設定し、さまざまなタイプのエラー処理のテストをカバーしました。ログとcatchハンドラーではエラーの構造が明確になり、それによってバグの検索時間が短縮されました。

利点:

  • 明確なタイプ階層のエラー
  • 信頼できるシリアル化
  • ブラウザとNode.js間のクロスプラットフォーム性

欠点:

  • 各CustomErrorクラスにおいてテンプレートロジックが発生しました