React redux typescript назначает два интерфейса для действия редуктора

Как я могу назначить функции reducer для действия в сценарии реакции два интерфейса: стандартный {type: string, payload: object} и redux-thunk?

reducer.ts

interface IReduxThunkAction {
  (dispatch: any): Promise<void>;
}
interface IActionPayload {
  type?: string;
  payload?: any;
}

type IAction = IActionPayload | IReduxThunkAction;

const reducer = (prevState = initialState, action: IAction): IInitialState => {
  switch (action.type) {
    case UPDATE_ITEMS:
      return updateItemsData(prevState, action.payload);
    default:
      return prevState;
  }
};

Вот эта ошибка:

Свойство type не существует для типа IAction. Свойство type не существует для типа IReduxThunkAction.

actions.ts

export const getItems = (
  term: string
): ThunkAction<Promise<void>, {}, {}, AnyAction> => {
  return (dispatch: ThunkDispatch<{}, {}, AnyAction>): Promise<void> => {
    return searchItems(term)
      .then(response => {
        const { results } = response.data;
        dispatch(updateItems(results));
      })
      .catch(() => {
        dispatch(fetchError());
      });
  };
};

ItemsList.tsx

// function with useReducer hook inside it

const [reducerState, dispatch] = useReducer(reducer, initialState);

// more code...

const handleSearch = (event: { preventDefault: () => void }) => {
    event.preventDefault();
    if (validateInput(state.value)) {
      dispatch(actions.changeSpinnerState());
      return dispatch(actions.getItems(state.value))
      .then(() =>
        dispatch(actions.changeSpinnerState())
      );
    }
  };

и здесь он сообщает мне онлайн-отправку (actions.getItems (state.value)):

Аргумент типа ThunkAction, {}, {}, AnyAction> не может быть назначен параметру типа IAction. Тип ThunkAction, {}, {}, AnyAction> не может быть назначен типу IReduxThunkAction.


person alex    schedule 23.11.2019    source источник
comment
Почему вы хотите назначить второй интерфейс своему редуктору? Зачем нужна диспетчеризация внутри редуктора?   -  person kind user    schedule 23.11.2019
comment
@kinduser Мне не нужна отправка внутри редуктора, но если я назначу только IActionPayload, то отправка (actions.getItems (state.value)) из файла ItemsList.tsx жалуется ... Как я могу это сделать?   -  person alex    schedule 23.11.2019
comment
Ваш getItems func меня как-то удивляет, почему вы отправляете рассылку? Почему вы обрабатываете побочные эффекты в создателе действий? Нигде в жизни не встречал такого подхода.   -  person kind user    schedule 23.11.2019
comment
@kinduser Я отредактировал код, который использую хуки, так что он исходит из хука useReducer   -  person alex    schedule 23.11.2019


Ответы (1)


Хорошо, я решил это:

ItemsList.tsx

const [reducerState, dispatch] = useReducer(reducer, initialState);

// more code...

const handleSearch = (event: { preventDefault: () => void }) => {
    event.preventDefault();
    if (validateInput(state.value)) {
      dispatch(actions.changeSpinnerState());
      dispatch(actions.changeSpinnerState());
      actions.getItems(state.value)(dispatch as IActionPayload);
    }
  };

actions.ts:

export const getItems = (term: string): React.Dispatch<IActionPayload> => {
  return (dispatch: any): Promise<void> => {
    return searchItems(term)
      .then(response => {
        const { results } = response.data;
        dispatch(actions.changeSpinnerState());
        dispatch(updateItems(results));
      })
      .catch(() => {
        dispatch(fetchError());
      });
  };
};

reducer.ts:

 const reducer = (prevState = initialState,  action: IActionPayload
): IInitialState => {
  switch (action.type) {
    case UPDATE_ITEMS:
      return updateItemsData(prevState, action.payload);
    default:
      return prevState;
  }
};

person alex    schedule 23.11.2019