Home > Blockchain >  Typescript and Reducer function with multiple payload options
Typescript and Reducer function with multiple payload options

Time:05-18

I'm very new to typescript and I'm trying to write a reducer function with three possible payload values : no value, a string, or a number. I'm using discriminated union type and from what I have read I think my code should work, but it is not.

type StateType = {
  isModalOpen: boolean;
  modalContent: string;
  people: {
    id: number;
    name: string;
  }[];
};

type NoPayloadAction = {
  type: string;
};

type NamePayloadAction = {
  type: string;
  payload: {
    name: string;
  };
};

type IdPayloadActionType = {
  type: string;
  payload: {
    id: number;
  };
};

type ActionType = NoPayloadAction | NamePayloadAction | IdPayloadActionType;

const ACTIONS = {
  ADD_ITEM: 'ADD_ITEM',
  NO_ACTION: 'NO_ACTION',
  CLOSE_MODAL: 'CLOSE_MODAL',
  REMOVE_ITEM: 'REMOVE_ITEM',
};

// reducer function
const reducer = (state: StateType, action: ActionType) => {
  switch (action.type) {
    case ACTIONS.ADD_ITEM:
      return {
        people: [
          ...state.people,
          { id: new Date().getTime(), name: action.payload.name },
        ],
        isModalOpen: true,
        modalContent: 'item added',
      };
    case ACTIONS.NO_ACTION:
      return { ...state, isModalOpen: true, modalContent: 'enter a value' };
    case ACTIONS.CLOSE_MODAL:
      return { ...state, isModalOpen: false, modalContent: '' };
    case ACTIONS.REMOVE_ITEM:
      const newPeople = state.people.filter(
        (person) => person.id !== action.payload.id
      );
      return {
        people: [...newPeople],
        isModalOpen: true,
        modalContent: 'item removed',
      };
    default:
      return state;
  }
};

Typescript is throwing two errors: The lines below throws this error: Property 'payload' does not exist on type 'ActionType'. Property 'payload' does not exist on type 'NoPayloadAction'

{ id: new Date().getTime(), name: action.payload.name },

(person) => person.id !== action.payload.id

The type NoPayloadAction does not have a payload, but the other two do and from what I understand they match their types as one has an id:number field and the other has a name:string field. I'm really puzzled by this.

CodePudding user response:

Right now, there is no guarantee that what is being passed in to your action variable is not a NoPayloadAction. If you are sure that your action variable does have a payload you can always use the as keyword tell typescript you know what the variable is. For example:

return { id: new Date().getTime(), name: (action as NamePayloadAction).payload.name },
  • Related