Changelog
- バージョン
0.3.0
になりました。
Enhancement
ok<T>(value: T)
という関数を追加しました。err<E>(error: E)
という関数を追加しました。
Deprecated
Ok<T>(value: T)
Err<E>(error: E)
経緯
先日、 WSL2 環境を Ubuntu 22.04 LTS に移行した。
環境が新しくなると整えたくなるもので、この移行に伴って dotfiles
の整備をはじめた。
以前からなんとなく気になっていた efm-langserver
を使ってみようと思い立った。
これは、 ESLint
などの linter が吐き出すメッセージを Language Server Protocol
(以下 LSP
) に載せ替えてくれるLanguage Serverだ。
ESLint+prettierの lint結果をLSP経由で扱えるだけでも便利だし、 zenn.dev に投稿する文書を textlint で校正もできるようになる。
これの実験にちょうどよいのが result.ts
だった。
ESLint
, prettier
, TypeScript
を使っていて、ボリュームも小さいからだ。
result.ts とは
ここで一旦説明をする。
result.ts
は Rust の Result
を真似て書いてみたものである。
export type ResultOk<T> = { isError: false; value: T; }; export type ResultErr<E> = { isError: true; error: E; }; export type Result<T, E> = ResultOk<T> | ResultErr<E>;
https://github.com/yajamon/result.ts/blob/75e33b52193f5f16e99d53b43b388616ab1967b6/src/main.ts#L1-L9
- こんな具合に、値かエラーを包んでいるオブジェクトは共通して
isError
を持っており、これを if でチェックするとスコープの中で型が確定できる。 - 個人的なこだわりは、
class
を使わず、ピュアなオブジェクトに包むことである。
シグネチャへの違和感
result.ts
だが、最終更新を確認すると2年以上前である。
これほど時間が経つと、当時とコードに対する感覚も変わってくる。
ふとコードを見ると違和感があった。
export const Ok: <T>(value: T) => ResultOk<T> = v => ({ isError: false, value: v }); export const Err: <E>(error: E) => ResultErr<E> = e => ({ isError: true, error: e });
TypeScript なのに関数がパスカルケース ( Ok(v)
, Err(e)
) なのだ。
当時の感覚としては、Rust の タプル構造体 を生成してるように見えて面白いからといった所だろうが、いくらなんでも寄せすぎた。
Rust においては、あくまで enum Result<T,E>
のいち構造体様の生成であり、関数ではない。
TypeScript / JavaScript において関数のシグネチャは、少なくともパスカルケースは主流ではない。
そしてオブジェクトの生成は new Ok(value)
などとするものだ。なんとも上記のコードでは気持ち悪さを感じる。
ということで ok(v)
と err(e)
を生やすこととした。
現行バージョンは 0.2.x
だし、シグネチャをまるっと変えても良いかなと思ったけれど、「わざわざ破壊しなくてもいいか」と思いとどまった。
代わりに @deprecated
アノテーションを付与した。