天天看點

TS 永遠達不到的類型never

避免出現新增了聯合類型沒有對應的實作,目的就是寫出類型絕對安全的代碼。

TypeScript 2.0引入了一個新原始類型never。never類型表示值的類型從不出現。具體而言,never是永不傳回函數的傳回類型,也是變量在類型保護中永不為true的類型。

never類型具有以下特征:

  • never是所有類型的子類型并且可以指派給所有類型。
  • 沒有類型是never的子類型或能指派給never(never類型本身除外)。
  • 在有明确never傳回類型注解的函數中,所有return語句(如果有的話)必須有never類型的表達式并且函數的終點必須是不可執行的。

比較直覺的代碼舉例:

interface Foo {
  type: 'foo'
}
interface Bar {
  type: 'bar'
}
type All = Foo | Bar
           

在 switch 當中判斷 type,TS 是可以收窄類型的 (discriminated union):

function handleValue(val: All) {
  switch (val.type) {
    case 'foo':
      // 這裡 val 被收窄為 Foo
      break
    case 'bar':
      // val 在這裡是 Bar
      break
    default:
      // val 在這裡是 never
      const exhaustiveCheck: never = val
      break
  }
}
           

注意在 default 裡面我們把被收窄為 never 的 val 指派給一個顯式聲明為 never 的變量。如果一切邏輯正确,那麼這裡應該能夠編譯通過。

但是假如後來有一天你的同僚改了 All 的類型:

type All = Foo | Bar | Baz

然而他忘記了在 handleValue 裡面加上針對 Baz 的處理邏輯,這個時候在 default branch 裡面 val 會被收窄為 Baz,導緻無法指派給 never,産生一個編譯錯誤。是以通過這個辦法,你可以確定 handleValue 總是窮盡 (exhaust) 了所有 All 的可能類型。

參考:知乎大佬們的回答

繼續閱讀