NGRX/Store payload type confusion

天涯浪子 提交于 2019-12-12 11:09:54

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!