问题
I have the following actions:
export const ActionTypes = {
CREATE_OH: type('[ORDERHEAD] Create Orderhead'),
MODIFY_SELECTED_OH: type('[ORDERHEAD] Select Orderhead'),
};
export class CreateOHAction implements Action {
type = ActionTypes.CREATE_OH
constructor(public payload: OrderHead[]) { }
}
export type Actions
= CreateOHAction
| SelectOHAction;
With the following base reducer setup
export interface State {
orderids: string[];
entities: { [orderID: string]: OrderHead };
selectedOhID: string | null;
};
// Set initial state to empty
const initialState: State = {
orderids : [],
entities: {},
selectedOhID: null,
};
export function OHreducer(state = initialState, action: orderhead_imp.Actions): State{
switch(action.type){
case orderhead_imp.ActionTypes.CREATE_OH:
let orders = action.payload;
let newOrders = orders.filter(orderhead => !state.entities[orderhead.orderID]);
let newOrderIds = newOrders.map(orderhead => orderhead.orderID);
let newOrderHeadEntities = newOrders.reduce((entities: { [orderID: string]: OrderHead }, orderhead: OrderHead) => {
return Object.assign(entities, {
[orderhead.orderID]: orderhead
});
}, {});
return {
orderids: [ ...state.orderids, ...newOrderIds ],
entities: Object.assign({}, state.entities, newOrderHeadEntities),
selectedOhID: state.selectedOhID
};
default:
return state;
};
}
This works fine, however, if I introduce another action:
export class SelectOHAction implements Action {
type = ActionTypes.MODIFY_SELECTED_OH
constructor(public payload: string) { }
}
Notice, the payload for this action only is string, as soon as this saved, or tried to compile, typescript now states: "filter does not exisit on type string|OrderHead[]"
Now if I go into my reducer, and add a new case:
case orderhead_imp.ActionTypes.MODIFY_SELECTED_OH: {
return {
orderids: state.orderids,
entities: state.entities,
selectedOhID: action.payload
};
}
I get the typescript errors when mapping action.payload of:
Throws the TS error "string|OrderHead[] is not assignable to type string"
Obviously in both cases the payload has a different data structure, do I need to change my code any other way to ensure each case is picking up the correct type for action.payload?
Update
So if in my actions I define the payload as "any" instead of "string" it seems to compile and work without issue, however this seems very hacky (and not the expected behaviour)
export class SelectOHAction implements Action {
type = ActionTypes.MODIFY_SELECTED_OH
constructor(public payload: any) { }
}
回答1:
This is an issue with Typescript >2.1 and the type util of ngrx.
With typescript 2.1 and above now you can simply define actions as
export const CREATE_OH: '[ORDERHEAD] Create Orderhead';
export class CreateOHAction implements Action {
type = CREATE_OH
constructor(public payload: OrderHead[]) { }
}
Now everywhere you used item.ActionTypes.CREATE_OH
, replace it with item.CREATE_OH
. The types will flow as expected with typescript 2.1
来源:https://stackoverflow.com/questions/41956607/ngrx-store-payload-type-confusion