【问题标题】:How do you define Flow types for Redux Actions?你如何定义 Redux Actions 的 Flow 类型?
【发布时间】:2017-08-25 10:05:37
【问题描述】:

我正在研究使用 Flow 输入 Redux 操作的方法。使用以下定义,它部分地在动作创建者和减速器中工作。自动完成将所有 4 个操作作为action.type 在两个位置的可能值。

// @flow
type ModuleActionTypes1 = 'moduleOne/ACTION_ONE' | 'moduleOne/ACTION_TWO';
type ModuleActionTypes2 = 'moduleTwo/ACTION_ONE' | 'moduleTwo/ACTION_TWO';

type ActionTypes = ModuleActionTypes1 | ModuleActionTypes2;

type Action<T> = {
  type: ActionTypes,
  payload: T
};

type Payload = {
  url: string
};

const actionCreator = (url: string): Action<Payload> => {
  return {
    type: 'moduleOne/ACTION_ONE',
    payload: {
      url: url
    }
  };
};

const reducer = (state: string, action: Action<Payload>): string => {

  if(action.type === 'wrong') {
    // action.type cannot be this 
  }

  switch (action.type) {
    case 'moduleOne/ACTION_ONE':
    case 'wrong': // action type cannot be this
      const { url } = action.payload;
      return url;
    default:
      return state;
  }
};

它几乎可以满足我的要求。主要有两个问题:

  1. switch case 不必是action.type 之一,因此拼写错误可能会漏掉。这表明我应该坚持使用字符串常量。

  2. 当我import type { ModuleActionTypes1 } from '../moduleOne';(而不是在同一个文件中定义它进行测试)时,自动完成功能停止工作,但流在命令行上没有报告任何错误。所有文件都包含@flow 注释。

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: javascript redux flowtype


    【解决方案1】:

    所以,这与您的问题有点不同,但让我建议您这样做有点不同。现在,您的操作类型表明任何有效负载都可以属于任何操作。如果您使用类型仅定义允许的状态,Flow 会更有帮助。

    我不知道你的行为是做什么的,所以这里是一个随机的例子:

    type CreatePerson = { type: 'create-person', person: Person };
    type DestroyPerson = { type: 'destroy-person', personId: number };
    type ChangePersonName = { type: 'change-name', personId: number, name: string }
    type PersonActions = CreatePerson | DestroyPerson | ChangePersonName
    

    以这种方式设置有助于确保每个 Redux 操作都具有正确类型的正确数据。在你的减速器中,你仍然可以在action.type 上进行 switch/if 来选择使用哪种情况。但是现在,通过按字符串选择类型,Flow 也可以准确地知道动作中存在什么类型的数据。这可以让您避免 Flow 无法进行类型检查的强制转换或不安全的解构。

    【讨论】:

    • 感谢您的回复。虽然这看起来有点简单,但它仍然存在类似的问题。如果我在 switch case 中得到正确的 action.type,则有效负载输入正确并且错误突出显示。如果我在 action.type 上打错字,则有效负载将输入为any,并且不会报告任何错误。这不如只使用字符串常量。
    • 我的目标是知道reducer正在检查一个不存在的action.type,所以很可能是错误的。
    • 我注意到这段代码按预期工作:type AorB = 'a' | 'b'; const reducer = (state: string, action: AorB) =&gt; { if(action === 'wrong') { // action.type cannot be this } }; 所以一定有一些关于它是一个包装对象的属性,它删除了枚举检查?
    • 是的,看起来就是这样。您的字符串版本工作正常,但除了使用具有类型属性的对象之外,同样的事情不会:type AorB = { type: 'a' } | { type: 'b' }; const reducer = (state: string, action: AorB) =&gt; { if (action.type === 'wrong') {}};
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    • 2017-07-23
    相关资源
    最近更新 更多