簡體   English   中英

不從減速器返回 state 時出現神秘的 TypeScript 錯誤消息

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM