質問: teratailに質問して回答がつかなかった質問が2つあります。 * TypeScriptでカスタムエラークラスを作成する方法について * HMACを使用したWeb API認証 上記の質問はなぜ回答がつかなかったのか、どのように質問していれば回答がついたのか。 今後のために、よろしければご指摘をいただけませんでしょうか。
回答: 改善点 * JavaScript - TypeScriptでカスタムエラークラスを作成する方法について(114258)|teratail 上記スレで改善できる点は下記の通り。 * **質問の見通しが悪い**と思いました。 (Typoraのようなアウトライン表示できるmarkdownエディタなら一定の合理性がありますが、teratailでは読みにくくて仕方ありません。) * 「前提条件」が**多すぎる**と思いました。他の方がコードを書く上で不要な情報は極力排除すべきと思います。**べき論**であれば、メリット/デメリットで事実が伝われば十分です。 以上を踏まえた質問文案を下記に示します。 質問文案 ### 質問 TypeScriptでカスタムエラーの3つの実装方法を記載しました。 自分ならXXXなのでこれを選ぶ、あるいはもっといい方法があるというようなご意見をいただきたいです。 ### コード ``` /** * (1) Errorをimplementsするクラスを作成する * @url https://books.google.co.jp/books?id=8m5qBgAAQBAJ&lpg=PP1&dq=isbn%3A4798139807&hl=ja&pg=PA195#v=onepage&q=ApplicationError&f=false */ class ApplicationError implements Error { public name = 'ApplicationError'; constructor(public message: string, public code: ApplicationErrorCode) { } toString() { return `${this.name}: ${this.message}`; } } /** * (2) Errorをextendsするクラスを作成する * @url https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work */ class FooError extends Error { constructor(m: string) { super(m); // Set the prototype explicitly. Object.setPrototypeOf(this, FooError.prototype); } sayHello() { return "hello " + this.message; } } /** * (3) Errorをカスタムするのではなく,throwをカスタムしてすべてErrorを使用する * @url https://www.htmlhifive.com/ */ /** * フレームワークエラーを発生させます。 * * @private * @param code {Number} エラーコード * @param msgParam {Any[]} フォーマットパラメータ * @param detail {Any} 追加のデータ(内容はAPIごとに異なる) */ function throwFwError(code, msgParam, detail) { ..... if (code) { e.code = code; } if (detail) { e.detail = detail; } throw e; } ``` ### 各手法のメリット/デメリット 1. Errorをimplementsするクラスを作成する 2. Errorをextendsするクラスを作成する 3. Errorをextendsするクラスを作成する | 手法 | メリット | デメリット | | --- | --- | --- | | 1 | アプリケーションの例外とJSの例外が分別できる( ネイティブのError 型は聖域として扱い、この種の例外を決してスローしないようにしよう。カスタム例外をApplicationError クラスのサブクラスとして作成すれば、本当に例外的な状況においてコードの外側で使用するためにError型を取っておくことができる。) | スタックトレースが取れない。 子クラスを作るたびにnameを書かないといけない(何らかの方法で解決できるのかもしれないが自分は分からない) | | 2 | スタックトレースが取れる | `Object.setPrototypeOf` を忘れたり誤ったりすると`instance instanceof FooError`がfalseになる。 TypeScript, Javascriptの仕様変更によって壊れる可能性が1より高い(実際にTypeScript2.1で壊れた) | | 3 | 全てのエラーはErrorなのでインターフェースが統一されている。 codeがenumであればdiscriminated unionsによって型の推論ができる。 | TypeScriptだとグローバルのError型定義を拡張しなければならない。 使用する側が気を付けなければならない。 | ### 前提条件 * Javascript(TypeScript)では極力例外を投げるのは避けるべきとは思っている * サポート対象ブラウザはChrome,FireFox,Safariの最新版のみ。デバイスはPC, タブレット, スマートフォン。 * TypeScriptを使用したSPA. ソースコード50000行ほど、ファイル数680 今後2倍くらいになりそう * フロントエンド監視にはSentryを使用している * JavascriptのErrorを拡張して,エラー種別の判別とSentryでのバグトラッキングに活かしたい(エラーコードを設けたり、エラー種別によってエラーハンドリングを変えたり) (※ここはどう省略すべきか不明な為、オリジナルのままです。) Re: u28epGUsk さん