Vinay Sharma
Vinay Sharma

Reputation: 3777

Typescript throws error when accessing payload in reducer

I have a reducer in which Typescript throws an error if I try to access formError property in the payload in the second switch case.

import actionTypes, { ActionCreatorType, ReducerType } from './types';

const initialState: ReducerType = {
  formError: '',
  responseSubmitted: false,
};

const enquiryFormReducer = (state = initialState, action: ActionCreatorType): ReducerType => {
  const { type, payload, } = action;

  switch (type) {
    case actionTypes.SUBMIT_FORM_SUCCESS:
      return {
        ...state,
        responseSubmitted: true,
        formError: '',
      };

    case actionTypes.SUBMIT_FORM_FAILURE:
      return {
        ...state,
        responseSubmitted: false,
        formError: payload.formError,
      };

    default:
      return state;
  }
};

export default enquiryFormReducer;

This is my types file.

const actionTypes = {
  SUBMIT_FORM_SUCCESS: 'SUBMIT_FORM_SUCCESS',
  SUBMIT_FORM_FAILURE: 'SUBMIT_FORM_FAILURE',
} as const;

interface FormErrorType {
  formError: string;
}

export interface SuccessActionType {
  type: typeof actionTypes.SUBMIT_FORM_SUCCESS;
  payload: {};
}

export interface FailureActionType {
  type: typeof actionTypes.SUBMIT_FORM_FAILURE;
  payload: FormErrorType;
}

export interface ReducerType {
  responseSubmitted: boolean;
  formError: string;
}

export type ActionCreatorType = | SuccessActionType | FailureActionType;

export default actionTypes;

You can see that the actionCreatorTypes is a union of all the actions are possible as per the switch case. But Typescript throws following error:

Property 'formError' does not exist on type '{} | FormErrorType'.
Property 'formError' does not exist on type '{}'

How do I solve this issue?

Upvotes: 0

Views: 488

Answers (1)

Maciej Sikora
Maciej Sikora

Reputation: 20132

The issue is destructuring. When you do so type stops be related to payload and not works as union discriminant anymore. Please use action.type and action.payload directly.

switch (action.type) { // direct use
    case actionTypes.SUBMIT_FORM_FAILURE:
      return {
        ...state,
        responseSubmitted: false,
        formError: action.payload.formError, // direct use
      };
    ...

Upvotes: 1

Related Questions