TypeScript でエラーハンドリングの抜け漏れ防止や開発者体験向上のために、Rust の Result 型のように trycatch するのではなく、返値でエラーハンドリングできないかを考えました。
Rust の Result 型は以下の通りで、エラーが発生しうる処理においては、正常に処理された場合もエラーの場合も返値として返されます。そして正常時は Ok(T) 型、エラーの場合は Err(E) 型として返されます。(T、E はジェネリクス。TypeScript と似てますね)
Result<T, E> is the type used for returning and propagating errors. It is an enum with the variants, Ok(T), representing success and containing a value, and Err(E), representing error and containing an error value.
enumResult<T,E>{Ok(T),Err(E),}
Functions return Result whenever errors are expected and recoverable. In the std crate, Result is most prominently used for I/O.
- std::result - Rust
上記 Rust の Result 型と同じようなことを TypeScript で実現してみたいと思います。
本記事の Result 型を使ったブラウザでのファイル読み込みの例を こちらの記事 で紹介しています。
The @throws tag allows you to document an error that a function might throw. You can include the @throws tag more than once in a single JSDoc comment.
- @throws | Use JSDoc
TypeScript では catch に渡される例外は unknown 型あるいは any 型です。tsconfig.json の compilerOptions.useUnknownInCatchVariable あるいは compilerOptions.strict が true の場合 unknown 型、false の場合 any 型になります。
Use Unknown In Catch Variables - useUnknownInCatchVariables
In TypeScript 4.0, support was added to allow changing the type of the variable in a catch clause from any to unknown.
- TypeScript: TSConfig リファレンス - すべてのTSConfigのオプションのドキュメント
まず _Result クラスがあり、それを継承した Ok クラスと Err クラスがあります。
_Result クラスは isOk() と isErr() メソッドを持っていて、返値の型が this is Ok<T> と this is Err<E> となっています。これは TypeScript の this -based type guards で if 文等でこれらのメソッドを呼ぶことで型を限定することができます。
You can use this is Type in the return position for methods in classes and interfaces. When mixed with a type narrowing (e.g. if statements) the type of the target object would be narrowed to the specified Type.
- TypeScript: Documentation - Classes
Ok クラスは value プロパティで正常時の返値を、Err クラスは error プロパティでエラー時の返値を保持します。プライベートプロパティーとゲッターを使用して読み取り専用にしています。