[英]cryptic TypeScript error message when not returning the state from a reducer
這是我為使用 React 練習 TS 而創建的一個簡單計數器的演示。
https://codesandbox.io/s/distracted-murdock-gtfv8?file=/src/App.tsx
在這里,我有一個這樣定義的減速器
function reducer(state: State, action: Action) {
switch (action.type) {
case actionType.INCREMENT: {
return { count: state.count + action.payload };
}
case actionType.DECREMENT: {
return { count: state.count + action.payload };
}
default:
neverReached(action);
}
return state;
}
這里neverReached
是一個工具 function 我用來捕獲未處理的案例。
const neverReached = (never: never) => {};
但是,如果我省略返回,即return state;
. TS 會在這一行引發錯誤const [state, dispatch] = React.useReducer(reducer, initialCount, init);
, 具體來說
var initialCount: number 沒有與此調用匹配的重載。 最后一個重載給出了以下錯誤。 'number' 類型的參數不能分配給'never' 類型的參數。
我似乎無法理解錯誤。 為什么我在reducer中省略return后會出現這種情況?
會發生什么?
當您在代碼中省略return
時,Typescript 會嘗試查找要調用的React.useReducer
重載,但找不到。 正如錯誤所說,錯誤是由最后一個重載發出的。
現在,最后的超載是什么? 發出的錯誤有助於提供以下信息:
index.d.ts(1002, 14):最后一個重載在這里聲明。
深入研究源代碼,我們可以看到這個重載是:
function useReducer<R extends Reducer<any, any>>(
reducer: R,
initialState: ReducerState<R>,
initializer?: undefined
): [ReducerState<R>, Dispatch<ReducerAction<R>>];
現在,與其過分思考這個重載的推斷類型是什么,我們只需將其復制粘貼到您的代碼中,然后直接調用它:
function useReducer<R extends React.Reducer<any, any>>(
reducer: R,
initialState: React.ReducerState<R>,
initializer?: undefined
): [React.ReducerState<R>, React.Dispatch<React.ReducerAction<R>>];
export default function App({ initialCount = 1 }: Props) {
useReducer(reducer, initialCount, init); // <-- called directly
}
我們現在可以直接調用useReducer
使用Reducer 並查看推斷的類型:
function useReducer<(state: State, action: Action) => {
count: number;
} | undefined>(reducer: (state: State, action: Action) => {
count: number;
} | undefined, initialState: never, initializer?: undefined): [...]
如您所見, initialState
推斷類型是never
,而傳入的initialCount
類型是number
,因此您會收到該錯誤消息。
為什么會發生?
當 Typescript 無法解析類型時,它會斷定它是never
類型。 根據文檔:
當任何不可能為真的類型保護縮小變量時,變量也會獲得類型
never
。
在您的代碼中,我們遇到的情況本質上類似於定義:
type resolvedAsNever = string & number
這是因為最后一個重載有initialState: ReducerState<R>
,而傳入的initialCount
類型是number
。 Typescript 無法從ReducerState<R> & number
中生成有效類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.