流类型 + Redux:不会与其他化简器的操作冲突的操作类型



我有一个用于存储首选项的化简器。它有两种操作类型。一个用于从数据库加载所有首选项,另一个用于更新单个首选项。我有一个工作的独立示例,但一旦在我的应用程序内使用,它就会中断。

问题是我的首选项化简器只处理两种类型的操作,而我的应用有多个化简器来触发其他操作。运行代码的解决方案是为与此化简器无关的操作添加第三个常规类型。但是,当我尝试访问操作的属性时,这会产生Property not found in 'object type'.错误。

工作流程示例

// @flow
const LOAD_PREFS_SUCCESS = 'LOAD_PREFS_SUCCESS';
const UPDATE_PREF = 'UPDATE_PREF';
type aType = {
+type: string
};
export type actionType = {
+type: typeof LOAD_PREFS_SUCCESS,
prefs: Array<{_id: string, value: any}>
} | {
+type: typeof UPDATE_PREF,
id: string,
value: any
};
export default (state: {} = {}, action: actionType) => {
if (action.type === LOAD_PREFS_SUCCESS) {
action.prefs.forEach(p => {
console.log(p);
});
}
switch (action.type) {
case LOAD_PREFS_SUCCESS: {
const newState = {};
action.prefs.forEach(p => {
newState[p._id] = p.value;
});
return newState;
}
case UPDATE_PREF: {
return { ...state, [action.id]: action.value };
}
default:
return state;
}
};

这是有效的流程,但是当应用程序实际运行时,当类型为INIT_APP或某些内容的操作运行时,我会收到错误。错误说action must be one of:,然后它列出了我在actionType中的两种类型作为预期和实际的{ type: string }

我可以通过向actionType添加第三种类型来运行应用程序,如下所示:

export type actionType = {
+type: typeof LOAD_PREFS_SUCCESS,
prefs: Array<{_id: string, value: any}>
} | {
+type: typeof UPDATE_PREF,
id: string,
value: any
} | {
+type: string
};

即使应用现在运行没有错误,它也不会通过流类型检查。抛出Property not found in object type错误。下面是一个关于 flow.org

由于每个化简器最终都会看到每个操作,因此你希望此化简器函数的类型包含应用中所有可能的操作。我通常定义一个变体actionType,其中包含应用程序中可用的所有内容,并在每个减速器中使用它。

上一个代码示例不起作用的原因是第三个匿名操作类型{type: string}太模糊。在此之前,Flow 可以查看操作中的两个选项,并根据case语句知道哪个选项是哪个选项。但是对于第三种操作类型,像{type: "LOAD_PREFS_SUCCESS"}这样的操作将与类型中的第三种情况匹配。因此,测试action.type === LOAD_PREFS_SUCCESS不再足以证明该操作将具有prefs键。

因此,有两种方法可以解决此问题:

如果将操作类型
  1. 更改为更具体并包含所有特定操作类型,则化简器应返回到类型检查。

  2. 否则,请添加一个虚拟案例,例如| {type: "NOT-REAL"},以便 Flow 强制您的化简器为其不理解的操作设置默认案例。

最新更新