今天我們會先介紹一段昨天的程式碼,認識甚麼是模式配對
,再衍伸到型別安全
。
昨天的這段程式碼就是在做模式配對
export const ErrorMessage: FC<TextInput> = (input) =>
pipe(
Match.value(input),
Match.tag('InvalidTextInput', (input) => <Displayed {...input} />),
Match.tag('InitialTextInput', (input) => <></>),
Match.tag('ValidTextInput', (input) => <></>),
Match.exhaustive
)
D04 - 設計資料模型 有提到過加上
_tag
後有助於我們做型別推演,其實這也是為了模式配對而準備的,可見它真的很重要 !
把上面的 code 用 TS 原生的方法寫看起來會像是這樣
const matchResult: FC<TextInput> = (input) => {
if (input._tag === 'InvalidCourseName') {
// 滑鼠移到 case1 會看到型別是 InvalidCourseName
return <Displayed {...input} />
}else if (input._tag === 'InitialTextInput'){
// 滑鼠移到 case2 會看到型別是 ValidCourseName | InitialCourseName
const <></>
}else if (input._tag === 'ValidTextInput'){
// 滑鼠移到 case2 會看到型別是 ValidCourseName | InitialCourseName
const <></>
}
}
原生方法看起來也很不錯,但會遇到一個問題
該怎麼保證沒有漏掉 ?
sum type
有個非常優秀的特性,就是易於擴展。如果需求變了,我們只要新增或移除其中一個型別,就可以直接刪除或新增一條邏輯分支,而不影響其他邏輯分支程式碼運行。但是使用原生的語法時,在你新增或刪除一個選項後,沒有辦法確保你剛好只處理且處理完所有型別。
但是使用
Match
可以
當你少一個選項,它會提醒你
當你多一個選項,它也會提醒你
類似這樣利用 type safety (型別安全) 來實現提早報錯的做法,其實很有價值。
不知道大家有沒有聽過軟體測試金字塔
,通常 unit test
位於最底層,UI 測試
位於最上層。越往上測試成本越高,發現錯誤時間越晚,修正錯誤所需的代價越大。
1991 年圖靈獎 Robin Milner 曾說
具備良好型別的程式從不出錯
而類似 Match
這樣的細緻的型別檢查與推演其實就是 FP 的專長,在一開始不熟悉 FP 的情況下,可能會看到滿滿的紅色毛毛蟲,佔據你的螢幕,讓你焦慮感爆棚。可是隨著越來越適應,你會發現它帶來的是無與倫比的安全感。