Reputation: 705
I ran into a flow error while doing essentially the basic redux-reducer example from flow docs.
Error from flow added to the code here: on the REMOVE
switch case: action
is not resolved to the correct type.
If i hover over payload
in vscode, in the ADD
case it displays it as AddAction
, but on REMOVE
case it is displayed as a union of all the actions, i.e. Action
.
What am i missing or understanding wrong? Flow should deduct the correct type down from the Actions
union to the only possible type(s) inside if
and switch
.
// @flow
const initialState = [];
type Item = { id: number, data: string };
type State = Item[];
type AddAction = {
type: 'ADD',
payload: Item
};
type RemoveAction = {
type: 'REMOVE',
payload: { id: number }
};
type ClearAction = {
type: 'CLEAR'
};
type Action = AddAction | RemoveAction | ClearAction;
const reducer: (State, Action) => State = (state = initialState, action) => {
switch (action.type) {
case 'ADD': {
return [...state, action.payload];
}
case 'REMOVE': {
return state.filter(t => t.id !== action.payload.id);
^ property `payload`. Property not found in
}
case 'CLEAR': {
return [];
}
default:
(action: empty);
return state;
}
};
export default reducer;
code on try flow
another try-flow repl where i do essentially the same thing and type inferring works as expected
Upvotes: 0
Views: 301
Reputation: 705
Ok, it seems that the problem was the use of action
inside Array.filter
arrow function:
If i replace the REMOVE
case contents with
case 'REMOVE': {
const id = action.payload.id;
return state.filter(t => t.id !== id);
}
the errors go away.
I guess flow cannot infer the type inside the arrow function. Would be interesting to know why.
edit: related question
So, flow invalidates the union refinement because it assumes filter() might be doing side effects to reducer parameter action
(docs). Storing the action or payload in a const before using fixes this.
Upvotes: 3