简体   繁体   中英

Redux Thunk Typescript Error On mapDispatchToProps

I'm experiencing a typescript error on my container component when trying to create my mapDispatchToProps function because my Thunk function doesn't return an object with property 'Type' in it. My Thunk returns a Promise, which itself doesn't have the 'Type' property, but does dispatch an action that does have 'Type' in it. I'm not sure how to tell typescript that this is ok.

The error I get is

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>'.

Action Types:

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;

Here's my dispatch on my component:

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
  }
};

Here are my actions:

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
  }
}
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));
    }
  }
}

Since this will be a thunk action creator you have to specify what type of action creator fetchJoke() is. you are using thunk action creator, but there is not any thunk type in your code.

You are saying that you are returnin Promise<void> but you have no return used in the function.

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM