TypeScript 中的 Redux Thunk

Redux Thunk in TypeScript

我正在尝试更好地了解 ThunkDispatch 函数和 TypeScript。获得了使用 redux 和 thunk 的代码。

// This is redux-thunk source code
import { Middleware, Action, AnyAction } from "redux";

export interface ThunkDispatch<S, E, A extends Action> {
  <T extends A>(action: T): T;
  <R>(asyncAction: ThunkAction<R, S, E, A>): R;
}

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

===================

import { Action } from 'redux'
import { ThunkAction } from 'redux-thunk'
import { ThunkDispatch } from 'redux-thunk'

interface ReduxState {
  // redux states
}

type ThunkResult<R> = ThunkAction<R, ReduxState, undefined, Action>
type ReduxDispatch = ThunkDispatch<ReduxState, undefined, Action>

const loadAppData = (): ThunkResult<void> => async (dispatch, getState) => {
  // get app data
  dispatch(MyAction.getAppDataSuccess(17))
}

const mapDispatchToProps = (dispatch: ReduxDispatch) => ({
  loadAppData: () => dispatch(loadAppData()),
})

我目前的理解:

export interface ThunkDispatch<S, E, A extends Action> {
  <T extends A>(action: T): T;
  <R>(asyncAction: ThunkAction<R, S, E, A>): R;
}

ThunkDispatch 是一个具有 2 个属性的接口,我们称它们为 A 和 B。A 是一个函数,其参数名为 action,类型为 T 和 return 是 T 类型的东西。类似地,对于 B,它是一个带有 asyncAction 类型的 ThunkAction<R, S, E, A> 参数和 return 类型的 R.

参数的函数

问题 <T extends A><R> 部分是否只是暗示一个新的泛型类型?

我目前的理解:

const mapDispatchToProps = (dispatch: ReduxDispatch) => ({
  loadAppData: () => dispatch(loadAppData()),
})

dispatch 作为参数是 ReduxDispatch 的一种类型,它是具有 2 个 属性 函数的接口。

loadAppData是一个将return类型ThunkResult<void>的函数,相当于ThunkAction<Void, ReduxState, undefined, Action>。如果我们将这些类型放入 ThunkAction 定义中,它会匹配 async (dispatch, getState) => { ... }

的签名

问题 mapDispatchToProps中的dispatch(loadAppData())loadAppData()、return是一个ThunkResult<void>,本质上是一个函数。 dispatch 只是一个带有 2 个 属性 函数的接口,那么这个语法对我来说没有意义,interface(func)

如果我有什么误解,请指出!谢谢

我个人无法在 TS 手册中找到对接口函数重载进行彻底解释的地方。

所有可用的是:

  1. Interfaces :: Function types
  2. Function overloads

如果你提供的声明我没记错的话

export interface ThunkDispatch<S, E, A extends Action> {
  <T extends A>(action: T): T;
  <R>(asyncAction: ThunkAction<R, S, E, A>): R;
}

可以以其他方式实现为以下 2 种函数类型的联合:

type ThunkDispatch<S, E, A extends Action> = (<T extends A>(action: T) => T) | (<R>(asyncAction: ThunkAction<R, S, E, A>) => R);

type ThunkDispatch<S, E, A extends Action> =
    | (<T extends A>(action: T) => T)
    | (<R>(asyncAction: ThunkAction<R, S, E, A>) => R);

虽然这是一个迟到的回复,但值得将其作为对这个问题的回答。来自 Redux Usage with Typescript:

Redux Thunk 是一种常用的中间件,用于编写与 Redux 存储交互的同步和异步逻辑。请随时在此处查看其文档。 thunk 是 returns 另一个接受参数 dispatch 和 getState 的函数。 Redux Thunk 有一个内置类型 ThunkAction,我们可以使用它来为这些参数定义类型:

import { Action } from 'redux'
import { sendMessage } from './store/chat/actions'
import { RootState } from './store'
import { ThunkAction } from 'redux-thunk'

export const thunkSendMessage = (
  message: string
): ThunkAction<void, RootState, unknown, Action<string>> => async dispatch => {
  const asyncResp = await exampleAPI()
  dispatch(
    sendMessage({
      message,
      user: asyncResp,
      timestamp: new Date().getTime()
    })
  )
}