Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Typescript and Reducer function with multiple payload options

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

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 },
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading