在本系列文中,所有的程式碼以及測試都可以在 should-i-use-fp-ts 找到,今日的範例放在 src/day-18
並且有測試可以讓大家練習。
昨天說到如果需要針對每個 bad path
都設計一個獨特的錯誤資訊,那使用 Option
就無法滿足需求,在這種情境下比較適合的 ADT
是 Either
,先來觀察 Either
的基礎型別。
// Either
type Left<E> = Readonly<{
_tag: 'Left';
left: E;
}>;
type Right<A> = Readonly<{
_tag: 'Right';
right: A;
}>;
type Either<E, A> = Left<E> | Right<A>;
看起來是不是跟 Day-07
的 Option
基本型別非常相似?
// Option
type None = Readonly<{
_tag: 'None';
}>
type Some<A> = Readonly<{
_tag: 'Some';
value: A;
}>
type Option<A> = None | Some<A>;
仔細觀察可以發現,兩者的主要差別只有在 sad path
(Left
, None
) 的情況,Either
的 Left
可以繼續承載資料,而 Option
的 None
沒有。
這一點可以讓我們擁有針對每個 sad path
有客製化結果資料的能力,但反過來說,我們需要處理每個 sad path
的資訊。
接下來來看 Left
和 Right
的基本建構子,可以看到預設型別都是 never
,這樣設計可以確保函式使用過程中,編譯器會及時顯示錯誤訊息 never is not ... type
,來讓我們開發流程中更有信心。
type LeftConstructor = <E = never, A = never>(e: E) => Either<E, A>;
const left: LeftConstructor = e => ({ _tag: 'Left', left: e });
type RightConstructor = <E = never, A = never>(a: A) => Either<E, A>;
const right: RightConstructor = a => ({ _tag: 'Right', right: a });
今天的主題在 should-i-use-fp-ts 在 src/day-18
並且有測試可以讓大家練習。