Javascript redux 操作缺少流联合类型 属性
Javascript flow union types missing property for redux action
我正在尝试学习如何使用 Flow,但我被困在这里。
我有一个接受不同类型操作的 redux reducer。每个动作的动作负载都不同,例如:
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,
}
这是我的减速器的一部分:
const MyReducer = (state: StateType, action: ActionType) = {
switch(action.type) {
...
case "WHATEVER":
....
var newChildrenArray = oldChildrenArray.filter((el) => {
return el != action.payload.childId;
})
....
}
}
这是 Flow 吐出的错误:
Cannot get action.payload.childId because:
• property childId is missing in String [1].
• property childId is missing in undefined [2].
• property childId is missing in Number [3].
src/redux/reducers/tasksReducer.js
57│ var oldChildrenArray = state[parentId].childrenIds
58│ var elementIndex = oldChildrenArray.indexOf(action.payload)
59│ var newChildrenArray = oldChildrenArray.filter((el) => {
60│ return el != action.payload.childId;
61│ })
62│ var newParentState = {
63│ ...state[parentId],
src/redux/actions/actionType.js
[1][2][3] 17│ payload?: string | number | TaskHandlerType ,
它正在检查操作负载是字符串或数字的情况,并警告这些类型没有 属性 childId,但这就是我在该分支上使用 switch 语句的原因,action.payload 将始终具有 childId。
那我怎么告诉 Flow 呢?
编辑:我刚刚注意到你的减速器正在开启action.payload
。也许应该改为打开 action.type
? OP 评论说这只是问题中的错字。
Flow 在推断 payload
的类型时遇到问题,因为它主要关心 action
参数的类型(表示 payload?: string | number | TaskHandlerType
),而不是值的具体形状你路过。
原因是:如果您添加 另一个具有相同类型但负载形状不同的 操作会发生什么情况?此操作可能如下所示:
{
type: 'WHATEVER',
payload: "foo"
}
并且 Flow 想要确保您的 reducer 能够处理它,因为根据 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
。
希望对您有所帮助,如有其他问题欢迎评论!
我正在尝试学习如何使用 Flow,但我被困在这里。
我有一个接受不同类型操作的 redux reducer。每个动作的动作负载都不同,例如:
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,
}
这是我的减速器的一部分:
const MyReducer = (state: StateType, action: ActionType) = {
switch(action.type) {
...
case "WHATEVER":
....
var newChildrenArray = oldChildrenArray.filter((el) => {
return el != action.payload.childId;
})
....
}
}
这是 Flow 吐出的错误:
Cannot get action.payload.childId because:
• property childId is missing in String [1].
• property childId is missing in undefined [2].
• property childId is missing in Number [3].
src/redux/reducers/tasksReducer.js
57│ var oldChildrenArray = state[parentId].childrenIds
58│ var elementIndex = oldChildrenArray.indexOf(action.payload)
59│ var newChildrenArray = oldChildrenArray.filter((el) => {
60│ return el != action.payload.childId;
61│ })
62│ var newParentState = {
63│ ...state[parentId],
src/redux/actions/actionType.js
[1][2][3] 17│ payload?: string | number | TaskHandlerType ,
它正在检查操作负载是字符串或数字的情况,并警告这些类型没有 属性 childId,但这就是我在该分支上使用 switch 语句的原因,action.payload 将始终具有 childId。
那我怎么告诉 Flow 呢?
编辑:我刚刚注意到你的减速器正在开启 OP 评论说这只是问题中的错字。action.payload
。也许应该改为打开 action.type
?
Flow 在推断 payload
的类型时遇到问题,因为它主要关心 action
参数的类型(表示 payload?: string | number | TaskHandlerType
),而不是值的具体形状你路过。
原因是:如果您添加 另一个具有相同类型但负载形状不同的 操作会发生什么情况?此操作可能如下所示:
{
type: 'WHATEVER',
payload: "foo"
}
并且 Flow 想要确保您的 reducer 能够处理它,因为根据 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
。
希望对您有所帮助,如有其他问题欢迎评论!