輸入關鍵字後會比對標題、標籤與內文摘要

找吧。

Article

Is Operator in Typescript

最近在寫 ts 發現了這個以前沒用過的 operator,筆記一下

Summary

總結來說,is 主要相信程式,as 主要是相信工程師,他們都無法準確檢查到邏輯錯誤

項目贏家原因
可維護性is邏輯集中管理
型別安全-都不驗證邏輯
重構友善is連動報錯機制
學習曲線as更直觀
工程價值is符合 SOLID 原則

is 的價值在於「把型別判斷邏輯變成可管理的單元」,這在大型專案中是巨大的優勢。

適用場景

適合用 as 的場景

  1. 單次使用、邏輯簡單
  2. 你 100% 確定型別(如 JSON.parse() 後)
  3. 原型開發、快速驗證
  4. 與外部無型別定義的 library 互動

適合用 is 的場景

  1. 邏輯會重複使用
  2. 需要在多個模組間共享
  3. 複雜的型別判斷(如區分 Union Type)
  4. 團隊協作、需要程式碼審查
  5. 需要為守衛邏輯寫測試

isas 的區別

決策流程圖

需要型別收窄?

  ├─ 否 → 不需要任何處理

  └─ 是

      ├─ 邏輯只用一次?
      │   └─ 是 → 用 `as`(簡潔)

      ├─ 需要抽離成函式?
      │   └─ 是 → 用 `is`(型別傳播)

      ├─ 邏輯重複 3+ 次?
      │   └─ 是 → 用 `is`(DRY)

      └─ 需要測試型別判斷邏輯?
          └─ 是 → 用 `is`(可測試)

基本比較

比較維度as (Type Assertion)is (Type Predicate)
基本語法value as Type(param): param is Type => boolean
使用位置任何表達式後面只能用在函式回傳型別
作用時機立即、單次轉換定義可復用的型別守衛
型別安全❌ 編譯器完全信任你,不驗證❌ 編譯器僅檢查型別兼容性,無法驗證邏輯正確性
Runtime 檢查❌ 無任何檢查✅ 必須配合實際判斷邏輯

程式碼複雜度

維度asis
Inline 使用✅ 簡潔 list.filter(x => !!x) as string[]⚠️ 略冗長 list.filter((x): x is string => !!x)
抽離函式❌ 需額外標註 filter(fn) as Type[]✅ 自動推斷 filter(guardFn)
多處使用❌ 每處都要寫 as✅ 定義一次,到處使用

可維護性

場景asis
邏輯變更❌ 需修改所有使用處✅ 只改函式定義處
型別變更⚠️ 必須手動更新每個 as Type✅ 函式簽名改了,所有呼叫處自動連動報錯
重構安全❌ 容易遺漏✅ 編譯器協助追蹤
Code Review⚠️ 審查者需檢查每個 as✅ 只需審查守衛函式本身

風險比較

風險類型asis
錯誤的型別斷言⚠️ 可用 as unknown as T 或是 as any 繞過,Runtime 爆炸⚠️ 直接編譯通過,Runtime 爆炸
邏輯與型別不一致🔴 高風險 - 分散在各處🟡 中風險 - 集中在一處
重構時遺漏更新🔴 高風險 - 編譯器不會提醒🟢 低風險 - 型別簽名變更會連動報錯
誤用範圍🔴 可在任何地方亂用🟢 只能在特定場景使用(函式回傳)

團隊協作

維度asis
新人理解成本🟢 低 - 直觀🟡 中 - 需理解 Type Guard 概念
程式碼審查🔴 每個 as 都是潛在風險點🟢 集中審查守衛函式即可
文檔價值❌ 無自文檔性✅ 函式名稱即文檔 (isValidUser, hasAllFields)
測試便利性❌ 無法獨立測試型別邏輯✅ 可對守衛函式寫單元測試

效能比較

維度asis
編譯後程式碼✅ 完全消失,零成本✅ 完全消失,零成本
Runtime 開銷✅ 無✅ 無(只是普通函式呼叫)
Bundle Size✅ 無影響⚠️ 若守衛函式複雜可能增加少量