Search code examples
typescriptreduxredux-thunk

Understanding Redux Thunk Typescript Generics and Types


I'm a little confused about the syntax of Redux Thunk in Typescript. I'm fairly new to Typescript but have an ok grasp of it, but there is a particular part that I don't understand.

Here is the type definition file for redux-thunk:

import { Middleware, Action, AnyAction } from "redux";

export interface ThunkDispatch<S, E, A extends Action> {
  <T extends A>(action: T): T; // I don't understand this line
  <R>(asyncAction: ThunkAction<R, S, E, A>): R; // or this line
}

export type ThunkAction<R, S, E, A extends Action> = (
  dispatch: ThunkDispatch<S, E, A>,
  getState: () => S,
  extraArgument: E
) => R;

export type ThunkMiddleware<S = {}, A extends Action = AnyAction, E = undefined> = Middleware<ThunkDispatch<S, E, A>, S, ThunkDispatch<S, E, A>>;

declare const thunk: ThunkMiddleware & {
  withExtraArgument<E>(extraArgument: E): ThunkMiddleware<{}, AnyAction, E>
}

export default thunk;

The part that I'm confused by is:

<T extends A>(action: T): T; // I don't understand this line
<R>(asyncAction: ThunkAction<R, S, E, A>): R; // or this line

I've looked at the documentation and it shows this:

interface GenericIdentityFn<T> {
    (arg: T): T;
}

function identity<T>(arg: T): T {
    return arg;
}

let myIdentity: GenericIdentityFn<number> = identity;

Does this mean then that a ThunkDispatch is a function, and that it can follow either of those two function signatures?

I can see from the Thunk Action that dispatch will always be a ThunkDispatch, but it's the ThunkDispatch interface that I can't make out.

It would be fantastic if someone could explain this for me.

Many thanks.


Solution

  • By default, store.dispatch(action) returns the dispatched action object.

    The line <T extends A>(action: T): T; is describing that behavior:

    • We dispatch an action object, and the type of the object is T
    • The return value of dispatch is that same object

    Similarly, for <R>(asyncAction: ThunkAction<R, S, E, A>): R:

    • R is the generic parameter for the return type of a particular thunk
    • When we dispatch that thunk, dispatch(thunk()) returns the result of the thunk

    And yes, that syntax is saying that ThunkDispatch is a function with two different overloads.