我正在研究使用Flow键入Redux操作的方法。使用以下定义,它在action actionor和reducer中都有部分工作。自动填充功能会将所有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;
}
};
它几乎可以满足我的需求。有两个主要问题:
切换案例不一定是action.type
之一,因此拼写错误可能会漏掉。这表明我应该坚持使用字符串常量。
当我import type { ModuleActionTypes1 } from '../moduleOne';
(而不是在同一个文件中定义它进行测试)时,自动完成功能会停止工作,但是流程报告命令行没有错误。所有文件都包含@flow评论。
有更好的方法吗?
答案 0 :(得分:0)
所以,这与你的问题有点不同,但是让我建议这样做有点不同。现在,您的操作类型表明任何有效负载都可以属于任何操作。如果您使用类型仅定义允许的状态,则流程可能会更有帮助。
我不知道你的行为是什么,所以这是一个随机的例子:
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
上进行切换/选择使用哪种情况。但现在,通过按字符串选择类型,Flow还确切知道操作中存在哪种类型的数据。这可以让您避免Flow无法进行类型检查的转换或不安全解构。