Search code examples
flowtypetypingreact-context

Getting Flow warning messages with Reducer


Using the React Context API, I've built this reducer:

export const usersReducer = (state: UsersState, action: UsersAction) => {
  switch (action.type) {
    case TOGGLE_MODAL: {
      return {
        ...state,
        isModalOpen: !state.isModalOpen
      };
    }

    case CANCEL_REQUEST: {
      return {
        ...state,
        isCancelRequest: action.payload
      };
    }

    case UPDATE_COMPANY: {
      return {
        ...state,
        companyId: action.payload
      };
    }

    default: {
      return state;
    }
  }
}

The associated Actions look like this:

// Note: `ActionType` = `string`
export const TOGGLE_MODAL: ActionType = 'TOGGLE_MODAL';
export const CANCEL_REQUEST: ActionType = 'CANCEL_REQUEST';
export const UPDATE_COMPANY: ActionType = 'UPDATE_COMPANY';

type ToggleModalAction = {type: typeof TOGGLE_MODAL};
type CancelRequestAction = {type: typeof CANCEL_REQUEST, payload: boolean};
type UpdateCompanyAction = {type: typeof UPDATE_COMPANY, payload: number};

export type UsersAction = 
     | ToggleModalAction
     | CancelRequestAction
     | UpdateCompanyAction;

On the two action.payload instances, Flow is saying this:

Cannot get `action.payload` because property `payload` is missing in  `ToggleModalAction`

I thought the way I defined my 3 "...Action" types, I could include payload where warranted and exclude it where it's not needed, like in ToggleModalAction.

Any ideas how to solve this?


Solution

  • By doing typeof TOGGLE_MODAL, etc., the type key of your UsersAction type will always be string. What you need in order to get type help from Flow's disjoint unions is the string literals themselves:

    type ToggleModalAction = {type: 'TOGGLE_MODAL'};
    type CancelRequestAction = {type: 'CANCEL_REQUEST', payload: boolean};
    type UpdateCompanyAction = {type: 'UPDATE_COMPANY', payload: number};