? ? never
類型是TypeScript中最特殊的類型之一,它表示永遠不會發生的值。作為專業前端工程師,理解never
類型對于編寫類型安全的代碼至關重要。
1.?never
類型的核心概念
定義:
never
類型表示永遠不會出現的值,常見于:拋出錯誤的函數(函數無法正常返回)
死循環函數(函數永不結束)
類型收窄后不可能存在的分支
關鍵特性:
never
是所有類型的子類型(可賦值給任意類型)除
never
本身外,沒有任何類型可賦值給never
基礎示例:
// 1. 拋出錯誤的函數
function throwError(msg: string): never {throw new Error(msg);
}// 2. 死循環
function infiniteLoop(): never {while (true) {}
}
2.?前端開發中的典型應用場景
類型收窄的窮盡檢查:
在聯合類型處理中,確保所有分支被覆蓋(如Redux reducer):
type Action = | { type: 'FETCH_START' }| { type: 'FETCH_SUCCESS', data: string[] }| { type: 'FETCH_FAIL', error: Error };function reducer(state: State, action: Action): State {switch (action.type) {case 'FETCH_START': return { ...state, loading: true };case 'FETCH_SUCCESS':return { loading: false, data: action.data };case 'FETCH_FAIL':return { loading: false, error: action.error };default:// 類型收窄后,action應為neverconst _exhaustiveCheck: never = action;return state;}
}
若新增FETCH_RETRY
類型但未處理,default
分支會因never
類型報錯(TS2345)
條件類型過濾:
在類型工具中排除特定類型:
// 剔除null和undefined
type NonNullable<T> = T extends null | undefined ? never : T;// 效果: string | number
type Cleaned = NonNullable<string | number | null>;
防御性編程:
標記不應到達的代碼分支(如React自定義hook):function useCustomHook(val: string | number) {if (typeof val === 'string') {// 處理字符串} else if (typeof val === 'number') {// 處理數字} else {// 標記不可能的分支const unreachable: never = val;throwError('Unexpected value'); // 調用never返回函數} }
3.?never
與其他類型的關系
類型 | 特性對比 | 典型用例 |
---|---|---|
never | 表示"不可能發生"的值 | 錯誤處理/窮盡檢查 |
void | 表示無返回值(返回undefined) | 無返回值的函數 |
unknown | 頂級類型,表示任意值但需類型斷言 | 第三方庫數據接收 |
any | 放棄類型檢查(禁用TS安全特性) | 兼容JS舊代碼(應避免使用) |
4.?優缺點與最佳實踐
優點:
增強類型安全:強制處理所有可能的分支(聯合類型)
自文檔化:明確標記不可達代碼
高級類型工具:實現類型邏輯過濾(如
Exclude<T, U>
)
缺點:
過度使用會增加代碼復雜度
新手易誤解其設計意圖
前端實踐建議:
在Redux/Vuex的reducer中必用窮盡檢查
自定義類型工具時優先使用never過濾無效類型
避免在基礎業務邏輯中濫用,保持代碼簡潔性
5.?總結
? ? never
類型是TypeScript類型系統的基石之一,它代表"不可能存在"的值的概念。在前端開發中,其主要價值在于:
實現編譯時的窮盡性檢查,避免分支遺漏導致的運行時錯誤
構建高級類型工具(如
Exclude
,NonNullable
)增強防御性編程能力,標記不應執行的代碼路徑
雖然日常業務代碼中直接使用頻率較低,但在構建可維護的大型前端項目(尤其是狀態管理庫和工具類型)時,never
是確保類型安全的終極防線。推薦在關鍵邏輯處理層(如reducer、parser)中積極采用,但在簡單組件中謹慎使用以保持代碼可讀性。