如何使用 Typescript 构建一个 react-redux reducer 来处理不同类型的有效负载?

How to structure a react-redux reducer with Typescript to handle different kinds of payloads?

所以,我正在尝试使用 React、Redux 和 TypeScript 构建一个 Todo 应用程序。将有一些待办事项页面,每个页面都会涉及待办事项。

以下是必要的类型和 Todos 状态。

export type Todo = {
  name: string;
  due: Date;
  color: string;
  pageId: string;
};

export type TodosByPageId = {
  [page: string]: Todo[];
}

export type TodosState = {
  byPageId: TodosByPageId;
  curPageId: string;
};

定义我的常量和动作后,我导出下面给定的减速器动作:

export type TodosAction = SetTodos | AddTodo | DeleteTodo | UpdateTodo | SetTodoPageId;

基本上

然后我开始定义todosReducer:

const initalState: TodosState = {
  byPageId: {},
  curPageId: '',
}

const todosReducer = (state: TodosState, action: TodosAction): TodosState => {
  switch(action.type) {
    case Constants.ADD_TODO:
      return state; // TODO
    case Constants.DELETE_TODO:
      return state; // TODO
    case Constants.SET_TODOS:
      return state; // TODO
    case Constants.SET_TODO_PAGE_ID:
      return { ...state, curPageId: action.payload };
    case Constants.UPDATE_TODO:
      return state; // TODO
    default:
      return state;
  }
}

在我处理的行 SET_TODO_PAGE_ID 给了我错误

Type 'string | Todo | Todo[]' is not assignable to type 'string'.
  Type 'Todo' is not assignable to type 'string'.

这是有道理的。每种情况下的类型转换似乎都不对,所以我想问一下这种情况下什么是更好的设计?

顺便说一下,我知道 redux 工具包是推荐的方式,但我只是想学习这两种风格。

我是 Redux 维护者。

如您所述:这里的第一个答案是 you should be using Redux Toolkit. We specifically recommend against trying to write reducers and actions by hand today. We do have a "Redux Fundamentals" tutorial 在我们的文档中显示了如何 hand-write Redux 代码,但 以便您了解基本机制。对于任何实际的应用程序,您应该使用 RTK。

第二个观察结果是 you should not be writing TS action type unions - 它们没有提供任何实际好处,并且实际上并不代表代码的运行方式。

请改用 our Redux TS Quick Start docs page 中显示的方法。