Search code examples
typescriptreduxredux-thunk

Dispatch is not returning a promise using redux-thunk with typescript


I'm actually migrating some code to typescript so I'm new in all this type stuff. When I used redux-thunk with regular javascript the dispatch method returned a promise that helped me to handle errors and stuff. The action was this one:

export const login = ({email, password}) => {
    return async function (dispatch) {
        try {
            const result = await api.post(`/auth/login`, {username, password});
            return dispatch({type: 'set_user_session', payload: result.data});
        } catch (err) {
            throw (err.response && err.response.data) || {code: err};
        }
    };
};

Then I called normally using the useDispatch hook:

const dispatch = useDispatch();
...
dispatch(login({username: "admin", password: "adminpassword1"}))
    .then(d => console.log("ok"))
    .catch(err => console.log(err));

Now that I migrated the code to typescript, the action now looks like this:

export const login = ({username, password}: Credentials): ThunkAction<Promise<Action>, {}, {}, AnyAction> => {
    // Invoke API
    return async (dispatch: ThunkDispatch<{}, {}, AnyAction>): Promise<Action> => {
        try {
            const result = await api.post(`/auth/login`, {username, password});
            return dispatch({type: 'set_user_session', payload: result.data});
        } catch (err) {
            console.log(err);
            throw (err.response && err.response.data) || {code: err};
        }
    }
}

This is executed without problems, but if I try to handle this:

dispatch(login({username: "admin", password: "adminpassword1"}))
    .then(d => console.log("ok"))
    .catch(err => console.log(err));

I get this error:

TS2339: Property 'then' does not exist on type 'ThunkAction   >, {}, {}, AnyAction>'

I tried to read the section about types in Redux but I cannot find the correct way to declare this dispatch function to work as I need it.

https://redux.js.org/recipes/usage-with-typescript

What's worse is that I'm getting this runtime error after the action is execute:

Possible Unhandled Promise Rejection (id: 0):

So the promise is somewhere.


Solution

  • The basic Dispatch type does not know about thunks. You need to infer the modified type of store.dispatch that tells TS that thunks are acceptable, and then it will understand that dispatching the thunk actually returns a promise.

    The best option here is to switch over to using our official Redux Toolkit package, and infer the type of store.dispatch as shown here:

    https://redux-toolkit.js.org/tutorials/typescript

    Then, you can use that improved Dispatch type with the useDispatch hook.

    (FWIW, redoing the Redux core docs "Usage with TS" page is on my todo list for the near-ish future)