Pesquisa de site

angular - NGRX/Store confusão de tipo de payload


Eu tenho as seguintes ações:

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;

Com a seguinte configuração básica de reducer

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;

    };
}

Isso funciona bem, no entanto, se eu introduzir outra ação:

export class SelectOHAction implements Action {
  type = ActionTypes.MODIFY_SELECTED_OH 

  constructor(public payload: string) { }
}

Observe, o payload apenas para esta ação é uma string, assim que isso é salvo, ou tentado compilar, o TypeScript agora declara: "filter não existe no tipo string|OrderHead[]"

Agora, se eu for para o meu reducer e adicionar um novo caso:

case orderhead_imp.ActionTypes.MODIFY_SELECTED_OH: {
 return {
  orderids:  state.orderids,
  entities: state.entities,
  selectedOhID: action.payload
};
}

Eu recebo os erros do TypeScript ao mapear action.payload de:

Gera o erro TS "string|OrderHead[] não é atribuível ao tipo string"

Obviamente, em ambos os casos, o payload tem uma estrutura de dados diferente. Preciso mudar meu código de alguma outra forma para garantir que cada caso esteja capturando o tipo correto para action.payload?

Atualização

Então, se em minhas ações eu definir o payload como "any" em vez de "string", parece que compila e funciona sem problemas, no entanto, isso parece muito improvisado (e não é o comportamento esperado)

export class SelectOHAction implements Action {
  type = ActionTypes.MODIFY_SELECTED_OH 

  constructor(public payload: any) { }
}

Resposta #1

Este é um problema com o Typescript >2.1 e o utilitário de tipos do ngrx.

Com o TypeScript 2.1 e superior, agora você pode simplesmente definir ações como

export const CREATE_OH: '[ORDERHEAD] Create Orderhead';
export class CreateOHAction implements Action {
   type = CREATE_OH

   constructor(public payload: OrderHead[]) { }
}

Agora, em todos os lugares onde você usou item.ActionTypes.CREATE_OH, substitua por item.CREATE_OH. Os tipos serão transmitidos como esperado com o TypeScript 2.1

Artigos relacionados