【问题标题】:Redux Thunk Typescript Error On mapDispatchToPropsmapDispatchToProps 上的 Redux Thunk Typescript 错误
【发布时间】:2018-12-17 16:18:51
【问题描述】:

我在尝试创建我的 mapDispatchToProps 函数时在我的容器组件上遇到打字错误,因为我的 Thunk 函数没有返回具有属性“类型”的对象。 My Thunk 返回一个 Promise,它本身没有 'Type' 属性,但确实调度了一个包含 'Type' 的动作。我不确定如何告诉 typescript 这没关系。

我得到的错误是

Argument of type '(dispatch: Dispatch<ActionTypes>, getState: () => IStoreState) => Promise<void>' is not assignable to parameter of type 'ActionTypes'.
Property 'type' is missing in type '(dispatch: Dispatch<ActionTypes>, getState: () => IStoreState) => Promise<void>'.

动作类型:

export interface IFetchJokeSuccessAction {
  readonly type: ActionTypeKeys.FETCH_JOKE_SUCCESS;
  readonly payload: string;
}

export interface IFetchJokeInProgressAction {
  payload: string;
  readonly type: ActionTypeKeys.FETCH_JOKE_INPROGRESS
}

export interface IFetchJokeFailAction {
  readonly type: ActionTypeKeys.FETCH_JOKE_FAIL;
  readonly payload: string;
}

export interface IClearJokeAction {
  readonly type: ActionTypeKeys.CLEAR_JOKE
}

type ActionTypes = IFetchJokeSuccessAction | IFetchJokeInProgressAction | IFetchJokeFailAction | IClearJokeAction;

这是我对组件的调度:

interface IDispatchProps {
  clearJoke: () => any;
  fetchJoke: () => any;
}
const mapDispatchToProps = (dispatch: Dispatch<ActionTypes>): IDispatchProps => {
  return {
    clearJoke: () => dispatch(clearJoke()), // No problem, this is a regular action
    fetchJoke: () => dispatch(fetchJoke()) // Problem, this is a Thunk
  }
};

这是我的行动:

import { Dispatch } from 'redux';
import { fetchJokeAPI } from '../api/jokeApi';
import IStoreState from '../store/IStoreState';
import { ActionTypeKeys as keys, ActionTypes, IClearJokeAction, IFetchJokeFailAction, IFetchJokeInProgressAction, IFetchJokeSuccessAction} from './ActionTypes';

export function fetchJoke(): (dispatch: Dispatch<ActionTypes>, getState: () => IStoreState) => Promise<void>  {
  return async (dispatch: Dispatch<IFetchJokeInProgressAction | IFetchJokeSuccessAction | IFetchJokeFailAction>, getState: () => IStoreState) => {
    dispatch(fetchJokeInProgress())
    try {
      const jokePayload = await fetchJokeAPI();

      dispatch(fetchJokeSuccess(jokePayload));
    } catch (err) {
      dispatch(fetchJokeFail(err));
    }
  }
}

export function fetchJokeSuccess(payload: string): IFetchJokeSuccessAction {
  return {
    payload,
    type: keys.FETCH_JOKE_SUCCESS,
  }
}

export function fetchJokeInProgress(): IFetchJokeInProgressAction {
  return {
    payload: 'Fetching a good joke.',
    type: keys.FETCH_JOKE_INPROGRESS
  }
}

export function fetchJokeFail(error: Error): IFetchJokeFailAction {
  return {
    payload: JSON.stringify(error),
    type: keys.FETCH_JOKE_FAIL
  }
}

【问题讨论】:

  • 迟了,但是:现在您可以使用 ThunkDispatch 代替 Dispatch 类型,涵盖这两种情况。 (从 redux-thunk 2.3 开始)

标签: reactjs typescript react-redux


【解决方案1】:
export function fetchJoke(): (dispatch: Dispatch<ActionTypes>, getState: () => IStoreState) => Promise<void>  {
  return async (dispatch: Dispatch<IFetchJokeInProgressAction | IFetchJokeSuccessAction | IFetchJokeFailAction>, getState: () => IStoreState) => {
    dispatch(fetchJokeInProgress())
    try {
      const jokePayload = await fetchJokeAPI();

      dispatch(fetchJokeSuccess(jokePayload));
    } catch (err) {
      dispatch(fetchJokeFail(err));
    }
  }
}

由于这将是一个 thunk 动作创建者,您必须指定 fetchJoke() 是什么类型的动作创建者。您正在使用 thunk 动作创建器,但您的代码中没有任何 thunk 类型。

你是说你正在返回Promise&lt;void&gt;,但你没有在函数中使用return

import { ThunkAction } from "redux-thunk";
import { Dispatch, ActionCreator } from "redux";

export const fetchJoke():ActionCreator<
ThunkAction<
  Promise<IFetchJokeSuccessAction|IFetchJokeFailAction>, //return value
  StoreState, // your app's store
  null, // this is extraArgument is passed to the thunk to fetch data
  IFetchJokeSuccessAction|IFetchJokeFailAction // which actions you are using in this thunk func
>
> =()=>  {
  return async (dispatch: Dispatch<ActionTypes>, getState: () => IStoreState) => {
    dispatch(fetchJokeInProgress())
    try {
      const jokePayload = await fetchJokeAPI(); 
      if(jokePayload){
        //  jokePayload could be undefined. setting type guard
        return dispatch(fetchJokeSuccess(jokePayload));
      }
    } catch (err) {
      return  dispatch(fetchJokeFail(err));
    }
  }
}

type ActionTypes = IFetchJokeSuccessAction | IFetchJokeInProgressAction | IFetchJokeFailAction | IClearJokeAction;

【讨论】: