如何使用 Typescript 在 Redux reducer 函数中实现详尽的 switch 语句?如何处理 Redux 的内部 @@redux 动作

How to implement an exhaustive switch statement inside a Redux reducer function using Typescript? How to handle Redux's internal @@redux actions

我试图找到一个明确的答案,但还没有找到。

SO 上有一个问题可以回答如何实施详尽的 switch 语句:

答案是:

编写一个函数,将 never 作为参数,returns never 并在调用任何内容时抛出异常。

function assertUnreachable(x: never): never {
  throw new Error("Didn't expect to get here");
}

并在您的 default 案例中使用它:

switch (action.type) {
  case "A": {
    ...
  }
  case "B": {
    ...
  }
  default: {
    return assertUnreachable(action);  // CAN'T USE action.type HERE BECAUSE action WILL BE never AND action.type WILL BE any
  }
}

但我不能在 reducer 中这样使用它。它会检查我的 reducer 操作的详尽性,但会在运行时抛出异常,因为 Redux 会用自己的内部操作调用它,例如:

@@redux/INITh.b.0.x.q.h                   // THIS IS THE action.type
@@redux/PROBE_UNKNOWN_ACTIONe.7.b.o.p     // THIS IS THE action.type

那么在 reducer 中处理 switch 语句穷举的理想方法是什么?

我在 Note on TypeScript's exhaustive type checks in scope of Redux's reducer 中找到了一个巧妙的解决方案。解决办法是:

  • 编译时触发错误
  • 不要在运行时抛出错误
function endReducer<T>(state: T, action: never): T {
    return state;
}

function reducer(state: State, action: Actions) {
    switch (action.type) {
        case ...

        default:
            return endReducer(state, action);
    }
}

Playground link

这里的正确答案是根本不用担心这个。

即使使用那个 switch 语句,你的 reducer 也会被其他动作调用。因此,尝试限制确切的操作集并没有多大帮助。

更好的方法是使用 our official Redux Toolkit package 中的 createSlice API,并让它定义您希望在该特定切片中处理的操作。