72
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TypeScriptにおけるエラー処理をどうするか

Last updated at Posted at 2020-09-26

この文章では、オライリーのプログラミングTypeScript に書かれている4種類のエラー処理方法について、利点と欠点を確認し、どの方法がよさそうかまとめてみる。

エラー処理方法

1. nullを返す

function date() {
  // -- エラー判定 -- 
  if (error) {
    return null
  }

  return new Date();
}
  • 利点
    • 簡単である。
    • 型安全である( 上記はstrictNullCheckが有効の場合、自動的にDate | null型になる。 )
  • 欠点
    • 詳細なエラー情報を伝えられない。

2. 例外をスローする

/**
 * @throws {RangeError} 日付のデータ形式が間違っている 
 */
function date(): Date {
  // -- エラー判定 -- 
  if (error) {
    throw new RangeError('正しいデータ形式で入力してください')
  }
  return new Date();
}
  • 利点
    • 詳細なエラー情報を伝えられる。
    • JavaScriptにおいて標準的な方法である。
  • 欠点
    • 型安全でない。型から例外がスローされるかどうか判断できない。コメントに書くしかない
    • スローされる可能性があるエラーの型がわからない。

3. エラーオブジェクトを返却する

function date(): Date | RangeError {
  if (error) {
    return new RangeError('正しいデータ形式で入力してください')
  }

  return new Date();
}


// 利用側
const myDate = date();
if(myDate instanceof RangeError) {
  alert("error");
}

  • 利点
    • 詳細なエラー情報を伝えられる。
    • 型安全である。
  • 欠点
    • 関数のネストを行うと、記述が冗長になっていく。

以下は冗長になっていく例。

function dateFormat(): Date | RangeError | InvalidDateFormatError | HogeError | FugaError {
  if (error) {
    return InvalidDateFormatError('正しいデータ形式で入力してください')
  }

  return date();
}

4. Option型を使う

Option型はHaskell、Rust、Scala等にある機能で、TypeScriptで使うには追加の依存ライブラリを必要とする。ここでは利点と欠点のみ示す。詳細説明は書籍(「プログラミングTypeScript」)を参照。

  • 利点
    • 型安全である
  • 欠点
    • エラーに関する詳細情報が型からはわからない
    • アプリケーション全体をOption型に依存して組み立てる必要がある。
    • 追加の依存ライブラリを必要とする

議論

 「1. nullを返す」はかなりありだと思う。まず、現在のTypeScriptであればnullチェック漏れのリスクはほぼない。strictNullCheckが有効になっている場合、関数のどこかでnullを返すと、型推論でDate | nullのように型をつけてくれ、ヌルチェックをしないとコンパイルエラーにしてくれるからだ。
 エラーの詳細がわからない問題はあるが、とはいえ「失敗した」ということを伝えたいだけのケースは多い。わざわざエラーの型、エラー内容を考えなくて済むのは楽である。

 また、別の言語の話にはなるがKotlinのAPI作法としてKotlinらしいAPIデザインにするには例外ではなくnullを返すというのがある。だからKotlinの標準APIにはString.toIntOrNull()というような名前のものがある。このようにエラーの意味でnullを返すというのは、null安全な言語だからできることである(コメント欄でも指摘されているが)。nullを返すということが実行時のリスクではないから、エラー処理の正当な方法として使えているわけだ。
 TypeScriptも2.0以降ではnullを安全に扱えるようになっているため、同様にエラー処理の正当な方法として利用できるはずである。

「2. 例外をスローする」についてはJavaScriptにおいて標準的な方法だが、型安全でないという問題があり、他の方法に比べて使いにくい。

「3. エラーオブジェクトを返却する」は型安全であり、基本的に良い。「1. nullを返す」で表現しきれない場合に使うなど、組み合わせても良い。記述が冗長になりうる欠点はあるが、実際に対応すべきエラーが陽に書かれて冗長になるのはリファクタリングの足がかりにもなるし、ひとまずは良いことである。

「4. Option型を使う」については独特な書き方になり外部ライブラリも必要である。実際の導入には「具体的にどういったライブラリが使え、それらの寿命はどうか」の評価も必要になるため、簡単に良い悪いを言うことが難しい。

結論

 ひとまず、「1. nullを返す」「3. エラーオブジェクトを返却する」の組み合わせが型安全かつ外部ライブラリも必要とせず、使い易そうである(strictNullCheckが有効である必要はある)。
 これを実用する場合、nullやエラーオブジェクトが返却されたときの意味をコメントで明示することや、それらが返却されうることを関数名で明示すること等々をすると良さそう。Kotlinのエラー処理作法も参考になる。

以上

72
50
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
72
50

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?