如何修复 redux-toolkit 中的打字稿错误?

suy*_*eon 9 typescript redux redux-toolkit

我正在用打字稿做一个 redux-toolkit 教程。但我是打字稿初学者。

我不知道这里出了什么问题。请给我你的见解。

这是一条错误消息。: TS2322: 类型“number”不可分配给类型“void |” 状态| 可写草稿'。

import {CaseReducer, createSlice, PayloadAction} from "@reduxjs/toolkit";

type State = {
  value: number
}
const increment: CaseReducer<State,PayloadAction<number>> = (state, action) => state.value + action.payload; // error line

export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0
  },
  reducers: {
    increment,
    decrement: state => {
      state.value -= 1
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload
    },
  },
})

export const {increment, decrement, incrementByAmount} = counterSlice.actions;

export default counterSlice.reducer;
Run Code Online (Sandbox Code Playgroud)

Lin*_*ste 10

没有大括号的箭头函数是隐含的 return。所以你要返回的state.value + action.payload是一个number.

Redux Toolkit 允许您返回新状态(State | WritableDraft<State>在回答此答案时键入,或键入State | Draft<State>较新版本的 RTK)或修改草稿状态而不返回任何内容(键入void)。您会收到 Typescript 错误,因为返回的number不是“两者”或“这些”。

您可能想要修改草稿状态,因此您需要在函数体周围加上大括号,这样您就不会返回任何内容。


这三个函数都是有效的。从最详细到最详细排序:

  1. 您可以使用加法赋值运算符直接增加值+=
const increment: CaseReducer<State,PayloadAction<number>> = (state, action) => {
  state.value += action.payload;
}
Run Code Online (Sandbox Code Playgroud)
  1. 您可以使用赋值运算符state.value为属性分配新值=
const increment: CaseReducer<State,PayloadAction<number>> = (state, action) => {
  state.value = state.value + action.payload;
}
Run Code Online (Sandbox Code Playgroud)
  1. (不推荐)您可以返回一个全新的状态。我在大括号周围使用括号来返回具有 property 的对象value
const increment: CaseReducer<State,PayloadAction<number>> = (state, action) => ({
  value: state.value + action.payload
});
Run Code Online (Sandbox Code Playgroud)

如果存在除value您之外的属性,则需要复制它们,就像{...state, value: newValue }您在传统 Redux 减速器中看到的那样。Redux Toolkit 提供了选项 1 和 2,因此您不必执行此操作。但如果您选择返回一个新状态,那么它必须是一个完整的状态。

  • @kevinTHEprogrammer “WritableDraft” 类型来自 immer,它是 Redux Toolkit 在幕后使用的用于不可变更新的包。`WritableDraft` 曾经由 Redux Toolkit 重新导出,但现在看起来他们已经改用 immer `Draft` 类型了。 (2认同)