为 Redux 操作定义类型的正确方法是什么?

What is the correct way to define types for Redux actions?

我有一个使用 Redux 进行状态管理的应用程序,我正在尝试添加 Flow 类型注释。

我在这里创建了一个非常简单的测试用例,概述了我 运行 遇到的问题。

我创建了一个 union Action 类型,然后在一个 reducer 函数中,我使用 switch 来根据操作的 return 决定什么状态type属性。在 switch 语句的每种情况下,我都在 action 参数上访问不同的属性。

我不明白为什么 Flow 告诉我它无法在 action 参数上找到某些属性。一切似乎都定义正确,我真的看不出这里有什么问题。

这是我的测试用例:

https://flowtype.org/try/#0C4TwDgpgBAggxsAlgewHZQLxQFBSgHygG8pRIAuKAcgDEBJAJQGUAVKgGigBMBDYHygHkARgCsICKAF9cBYqXARKVJgFEAwoIByAEQ5REwCAFs6XSgGdgAJ0SoA5tOzYy0JvyOZisgDaIrlDDW1jwgADwi4ggAfOzYMtgAZgCuqAgo6NYQXMlwEAAUVnxKUO7FnDzpaIFVqACUlKjJxsIQ1t54FgDuhnAAFlD5lUhoAHSudR14UHA8FtC0jKxUlESy01BZwMnW6EVGo35Wo4l2XHSoXBAAHvmGJpjRBkbGo4hcmBhYwxmjvPxvLh1ADc6ycG1m82oak0uhWUw2Wx2ew8EEO-mAJzOFyut3uxkezxMgM+31qbxeZhBYJkGyuiR4yR8wHIYLwSN2UAADKC8DIpEA

我认为可能问题与使用switch语句有关,所以这是一个使用if的版本,有同样的问题:

https://flowtype.org/try/#0C4TwDgpgBAggxsAlgewHZQLxQFBSgHygG8pRIAuKAcgDEBJAJQGUAVKgGigBMBDYHygHkARgCsICKAF9cBYqXARKVJgFEAwoIByAEQ5REwCAFs6XSgGdgAJ0SoA5tOzYy0JvyOZisgDaIrlDDW1jwgADwi4ggAfOzYMtgAZgCuqAgo6NYQXMlwEAAUVnxKUO7FnDzpaIFVqACUlKjJxsIQ1t54iIlQ+ZVIaAB0rpgYWLSMrFR1HXhQWcDJ1uhFRgN+VgOJdlx0qFwQAB75hiaY0QZGxgOIXCNYfRkDvPzXXHUA3LIyeLJdPQ+DYajMZqTS6KYzPDzRbLDwQNb+YCbba7fZHE7GM4XEyvO5QAGoa6XMwfL6yWTQpZQAAMnykQA

首先,请注意您的 reduce 函数不是有效的减速器。 redux reducer 必须具有以下签名

(state: State, action: Action) => State

Flow 对改进持悲观态度(理论上您可以更改回调中的 action.data 引用)。帮助 Flow 保持精炼的一种方法是使用 const 绑定 (docs)

function reduce(state: State, action: Action): number {
  switch (action.type) {
    case 'FIRST': 
      const data = action.data;
      return state.list.findIndex(item => item.id === data.id);
    case 'SECOND': 
      const itemId = action.itemId
      return state.list.findIndex(item => item.id === itemId);
    default:
      return 0;
  }
}

或者,IMO 更好,将案例分成几个辅助函数

function findIndex(state: State, id): number {
  return state.list.findIndex(item => item.id === id);
}

function reduce(state: State, action: Action): number {
  switch (action.type) {
    case 'FIRST': 
      return findIndex(state, action.data.id)
    case 'SECOND': 
      return findIndex(state, action.itemId)
    default:
      return 0;
  }
}

此外,您可以在 redux 存储库中找到流式应用的示例(参见 examples/todos-flow)