Go
error
TypeScript
例外
Try-Catch

🔵 TypeScriptでもGoみたいに「例外を投げない」ためのライブラリを作った

yamaimo (@yarnaimodev) です。

先日この記事を読みました。

「例外を投げない」という選択肢をとる言語

Go や Scala では、例外を JavaScript のように throw して catch することが推奨されず、多値返却や Either でエラーも戻り値として返すアプローチがとられるという内容です。

TypeScript でも同じようなことがしたかったので fp-ts を使って作ってみました!!!🎉🎉

⛵ TrySafe

https://github.com/yarnaimo/trysafe

yarn add trysafe か npm i -S trysafe でインストールできます🙃

どっかで見たことあるような名前ですが気のせいです。


使い方

import { Try, TryAsync } from 'trysafe'

const result = Try(() => {
return document.querySelector('a')!.href // 要素が見つからない場合はエラーが throw される
})

// この場合 result の型は Either<Error, string>

if (result.isLeft()) {
// ここでは result.value の型は Error
console.error(result.value.message) // -> エラーメッセージ
return
}

// ここでは result.value の型は string
console.log(result.value) // -> href の値

Try には引数のない関数 () => T を渡します。

Try の戻り値の型は fp-ts の Either<Error, T> で、これは Left 型と Right 型の Union Type です。

渡された関数の中でエラーが throw された場合は Left、成功した場合は Right が返され、.isLeft() と .isRight() で判別することができます。

async 関数を渡したい場合は TryAsync を使います。

const result = await TryAsync(async () => {

return await fetch('http://example.com')
})


普通の try-catch と比べていいところ


「エラーが起きる可能性」を明示できる (try-catch を忘れることがない)

例えばこんな関数があったとします。

async function getUsers() {

return fetch('/users')
}

この関数はエラーを throw する場合があるので上流で catch すべきですが、特にネストが深い場合などは忘れてしまう可能性もあります。

async function getUsers() {

return TryAsync(async () => fetch('/users'))
}

Try で囲むと、エラーが発生した場合も外には throw されずに戻り値で返されるのでその心配はありません。


エラーが握りつぶされにくい

エラーを上流で処理するような設計にしやすいので、下流でエラーを握りつぶしてしまう可能性も減るのではないかと思います。


あとがき

今回の内容とは関係ないんですが、fp-ts といえば実行時に型チェックをするための io-ts っていうライブラリもあります。

終わりだよ〜