Search code examples
typescriptreduxreact-reduxredux-thunkdispatch

How to correctly type redux-thunk actions & mapDispatchToProps with redux 4.0.1, redux-thunk 2.3.0 & typescript 3.1.3


I'm updating the dependencies in my project (redux 4.0.1, redux-thunk 2.3.0, typescript 3.1.3) and I'm having a very hard time finding the correct typings for redux-thunk in both my action declaration as my mapDispatchToProps declaration.

For example, I have the following actions:

Normal redux action

export interface UpdateRowContent {
    type: typeof Actions.UPDATE_ROW_CONTENT;
    payload: React.ReactNode[];
}
export const updateRowContent: ActionCreator<Action> = (content: React.ReactNode[]) => {
    return { type: Actions.UPDATE_ROW_CONTENT, payload: content};
};

Redux-thunk action

export interface ToggleModalShown {
    type: typeof Actions.TOGGLE_MODAL_SHOWN;
    payload: {
        isShown: boolean;
        targetType: TargetType;
        packageItemId?: string;
    };
}
export function toggleModalShown(
    isShown: boolean,
    targetType: TargetType,
    packageItemId?: string,
): any {
    return (dispatch: Dispatch<any>) => {
        if (isShown) {
            dispatch(clearForm());
        } else if (packageItemId) {
            dispatch(fillForm(packageItemId));
        }
        dispatch({
            type: Actions.TOGGLE_MODAL_SHOWN,
            payload: {isShown: isShown, targetType: targetType, packageItemId: packageItemId ? packageItemId : null},
        });
    };
}

My mapDispatchToProps is as follows:

type DispatchType = Dispatch<Action> | ThunkDispatch<IState, any, Action>;

function mapDispatchToProps(dispatch: DispatchType) {
    return {
        updateRowContent: (content: React.ReactNode[]) => {
            dispatch(updateRowContent(content));
        },
        toggleModalShown: (isShown: boolean, targetType: TargetType) => {
            dispatch(toggleModalShown(isShown, targetType));
        },
    };
}

All the things I find online tell me to type the mapDispatchToProps as ThunkDispatch<S,E,A>, which is what I'm currently trying to do. The guides tell me to type the actual thunk-action as ActionCreator<ThunkAction<R,S,E,A>>

When I try to use ActionCreator<ThunkAction<void,IState,any,Action>> instead of any as type for my redux-thunk, I get the error Argument of type 'ActionCreator<ThunkAction<void, GoState, any, Action<any>>>' is not assignable to parameter of type 'Action<any>'.

Any ideas?


Solution

  • Allright, I made a silly mistake in my dispatch typing...

    type DispatchType = Dispatch<Action> | ThunkDispatch<IState, any, Action>;
    function mapDispatchToProps(dispatch: DispatchType) {...}
    

    should be

    type DispatchType = Dispatch<Action> & ThunkDispatch<IState, any, Action>;
    function mapDispatchToProps(dispatch: DispatchType) {...}
    

    After fixing that I found out that my redux-thunk action type should be

    export function toggleModalShown(): ThunkAction<void, IState, any, Action> {...}
    

    instead of

    export function toggleModalShown(): ActionCreator<ThunkAction<void, IState, any, Action>> {...}