Javascript流联合类型缺少Redux操作的属性

时间:2018-07-08 23:09:35

标签: javascript redux flowtype

我正在尝试学习如何使用Flow,但是我被困在这里。

我有一个redux减速器,可以接受不同类型的动作。每个操作的操作有效载荷都不同,例如:

›v[Ù³›.ˆvíæeË.Ù.öc‘ÊŠh±~Lb‘ÚY¯,u‰%­ÛcÒiÒB'    Ý}Š©xêKY²,N¯Ó>=Šì/ð÷së©<?‚L‘ KËåž¿—_ÎÛ=—9½ˆžÈ“‹Á¾%Âñÿðó‚$ƒQ$|=…âHC¨Aãï—ÁT²wb¿go¨‹$>¬J+¾êÀ9@AÝȪÈ]ZQÞÂZ¨¾Ù%´Y覆ê¬àþd1 Eá¿1WËǸׇìM„—ú+W3õ†@†%Bú$‰j —?m/Ú·±à¬¹TT¥Zª¯ZVªóIeô—¾’Þš»rÉýŠ{u— Pè»ÈYÈ uzü‰ŸyQÛ8?ƒú<øúå.¼¾§rÙ$Õ)dÑ©ñÜ  A8@/ð(.Âï¨fªªj8lP

动作有效载荷的类型如下:

const CreateNewTaskAction = (n: number) => {
    return {type: "CREATE", payload: n};
}

const AnotherAction = (r: TaskHandlerType) => {
    return {type: "WHATEVER", payload: r}
}

这是我的减速器的一部分:

type TaskHandlerType = {
    ...
    childId: number,
    parentId: number,
}                                                       


export type ActionType = {                                                       
    type: string,                                                                
    payload?: string | number | TaskHandlerType,
}         

这是Flow吐出的错误:

const MyReducer = (state: StateType, action: ActionType) = {
    switch(action.type) {
        ...
        case "WHATEVER":
            ....
            var newChildrenArray = oldChildrenArray.filter((el) => {   
                return el != action.payload.childId;                   
            })                                                         
            ....

        }
    }

它正在检查动作有效载荷为字符串或数字的情况,并警告这些类型不具有属性childId,但这就是为什么我在该分支上使用switch语句的情况,action.payload始终具有childId。

那我该如何告诉Flow?

1 个答案:

答案 0 :(得分:1)

编辑我刚刚注意到您的减速器正在打开action.payload。也许OP应该打开action.type吗? OP评论说这只是问题中的错字。

Flow很难推断出payload的类型,因为它主要关心action参数的类型(表示payload?: string | number | TaskHandlerType),而不是您所关注的值的特定形状重新传递。

原因是:如果添加具有相同类型但有效负载形状不同的另一个动作,将会发生什么?此操作可能类似于:

{
  type: 'WHATEVER',
  payload: "foo"
}

并且Flow想要确保您的减速器能够处理它,因为根据TaskHandlerType,此操作是有效的。当然,不会这样做,因为Redux动作type必须是唯一的,但是Flow不知道。

基本上有一个假设–只能用特定的type定义一个动作,而其payload的形状将始终相同– Flow不可见。我不认为Flow具有任何内置功能可以直接表达这一点……但是,幸运的是,还有另一种解决问题的方法(尽管有更多样板)。

您可以使用union type(类似于payload中的TaskHandlerType的类型)来告诉Flow每个特定消息的确切形状。一种方法是这样的:

// Actions

type CreateNewTaskActionType = {| type: "CREATE", payload: number |};
const CreateNewTaskAction = (n: number): CreateNewTaskActionType => ({
    type: "CREATE",
    payload: n
});

type AnotherActionType = {| type: "WHATEVER", payload: TaskHandlerType |};
const AnotherAction = (r: TaskHandlerType): AnotherActionType => ({
    type: "WHATEVER",
    payload: r
});

// Types

type ActionType = CreateNewTaskActionType | AnotherActionType;

现在,Flow可以知道带有type: "WHATEVER"的值肯定具有payload类型的TaskHandlerType

Interactive demo

希望这会有所帮助,如果还有其他问题,请发表评论!