type
status
date
slug
summary
tags
category
icon
password

背景

在現代的前端開發中,TypeScript 是一個極為流行且廣泛應用的技術。作為一種基於 JavaScript 的強型別程式語言,TypeScript 提供了型別檢查和編譯時錯誤檢測,使得前端應用能夠在可靠性以及可維護性和開發效率方面,獲得更高的水準且擁有強大的型別系統,同時也能夠在開發過程中捕捉到潛在的錯誤,從而減少了運行時錯誤的風險。
但通常事實都不是如同想像中的美好,尤其是在使用外部資料時。 因為實際上 TypeScript 是在編譯時運作,而不是在 runtime。
notion image

將外部資料映射到類型

假設我們從 API 拿到一個 todo 的資料
我們為這份資料建立一個 interface,並使用 axios 獲取資料
當 API 回傳的結果不如預期,假設回傳的結果是
Todo 這個型別依然會把 done 當成 boolean,但 JavaScript 則是將他視為字串。 因為實際上 TypeScript 是在編譯時運作,而不是在 runtime。
如果現在要做點什麼,可能是寫一個驗證的 function 檢查下列幾點。
  1. 資料是否為 object
  1. id 是否存在且型別是 number
  1. content 是否存在且型別是 string
  1. done 是否存在且型別是 boolean
這麼做是可行的,但如果遇到更複雜的型別,我們會很崩潰。

Zod 閃亮登場✨

TypeScript-first schema validation with static type inference - Zod
使用 Zod 你只需要定義 schema 他就能應用於驗證與產生型別。
讓我們回到上面的情境並使用 Zod。 Todo 可以這麼被定義以及推導出型別,並驗證資料。
我們現在有了 Todo 的型別和驗證過的資料。
我們接著看看另一個情境 現在我們要做一個簡易的登入表單,使用 email & password 登入。並搭配 React Hook Form
我們也只需要定義登入表單的 schema,就能完成表單驗證的部分。
透過上面兩個情境,我們不再害怕 API 回傳的資料格式變動所造成不預期的錯誤, 我們只要定義好 schema 同時也節省了許多驗證使用者輸入資料以及定義型別的工作。

我們接著看看再複雜一點點的情境

現在我們要做一個註冊表單,
這次多了一些規則而且需要填入的資訊也多了一些,需要使用者填入信箱、密碼、名稱、年齡等,
限制了密碼長度最少要 8 個字元,名稱則是介於 2 - 30 個字元,年齡則是非必填的但是填入時需要是大於零的整數
我們也只需要定義註冊表單的 schema,就能完成表單驗證的部分。

實務應用

Typescript to Zod Schema

這邊用 KOL Radar 的項目為例。
KOL Radar 也導入了 Zod,在一開始轉換的過程中是使用 transform.tools 提供的工具將既有的 Typescript interface 先初步轉換成 Zod Schema,再根據實際的細節做調整。

結合 RTK Query

KOL Radar 使用 RTK Query 來處理 data fetching and caching。因此除了驗證使用者輸入之外我們也需要驗證 API 資料,因此需要結合 RTK Query。
一開始他們是在 RTK Query 中的 transformResponse 進行資料驗證並在驗證錯誤時噴出錯誤。
之後他們使用一個 Higher-Order Function zodBaseQueryWrapper 統一處理 RTK Query 的驗證問題。
在進行 baseQuery 之前,會先進行對於傳入參數的驗證,
並且同樣對 baseQuery 回傳的結果進行驗證。
不熟悉 RTK Query 也沒關係,這裡主要的部分還是使用 Zod parse 來驗證資料及拋出錯誤。

相關工具比較

當然也有許多其他的工具提供類似的功能礙於篇幅與主題的緣故再這不一一說明,
官網有寫出相關的內容如果對於以下 package 有興趣的可以看看 Zod 點出的差異。
Comparison with Joi、Yup、io-ts、Runtypes、Ow

小結

理解了 TypeScript 在 compile 以及 runtime 的差異。在使用者輸入資料或者是在使用外部資料時,更需要驗證工具來幫助我們。這時候 Zod 就會是一個很棒且使用成本很低的工具,即使你使用的是 JavaScript 也依然適用!
  • 註:上述內容皆為 untested pseudocode

React 原碼中的 Lane 是什麼
React 原碼中的 Lane 是什麼
Announcement
type
status
date
slug
summary
tags
category
icon
password
🎉新版博客即將到來🎉
-- 感谢您的注意 ---
👏為您帶來愉快的體驗👏