带有 Typescript 的 Redux Thunk

Posted

技术标签:

【中文标题】带有 Typescript 的 Redux Thunk【英文标题】:Redux Thunk with Typescript 【发布时间】:2019-11-14 06:38:15 【问题描述】:

我正在学习 Typescript,我正在尝试实现一个简单的 React/Redux 应用程序。当我使用同步操作时,它工作正常,但问题在于异步操作。我正在关注官方的 redux 教程。

首先我声明会话的状态

export interface UserSessionState 
  loggedIn: boolean;

然后我声明动作的接口

interface UpdateSessionAction 
  type: 'USER_LOGIN';
  payload: boolean;

我用联合类型导出它们

export type UserActionTypes = UpdateSessionAction;

然后我有实际的行动


export function updateSession(loggedIn: UserSessionState) 
  return 
    type: 'USER_LOGIN',
    payload: loggedIn,
  ;

我有一个虚假的 api 调用

function api() 
  return Promise.resolve(true);

最后是登录

export const userLogin = (): ThunkAction<
  void,
  ,
  ,
  AnyAction
> => async (dispatch: ThunkDispatch<, , AnyAction>) => 
  const res = await api();
  dispatch(updateSession( loggedIn: res ));
;

在reducer中我只是初始化状态

initialState: UserSessionState = loggedIn: false

然后我为 reducer 做正常的 redux 工作。

最后在我的商店中,我调用了检查状态的初始操作

store.dispatch(userLogin());

我不断收到此错误:

Argument of type 'ThunkAction<Promise<void>, , , AnyAction>' is not assignable to parameter of type 'AnyAction'.
  Property 'type' is missing in type 'ThunkAction<Promise<void>, , , AnyAction>' but required in type 'AnyAction'.

我错过了type,但我不知道我做错了什么。

【问题讨论】:

在更新会话中,您返回一个类型为 USER_LOGIN 的操作,但这不是界面中的字符串 - 您是否在其他地方声明过?如果不是,您将希望将其设为字符串 是的,这是一个导出的普通常量export const USER_LOGIN = 'USER_LOGIN';,我编辑了我的问题只是为了清楚起见,谢谢 【参考方案1】:

简而言之:

您收到此错误是因为从您的userLogin() 函数返回的是ThunkAction,缺少type

为什么会这样?

dispatch 应该接受AnyAction 类型的参数。 AnyAction 是一个 redux 类型,它扩展了 Action(它有一个强制属性 type)。

这是来自当前的redux types file

export interface Action<T = any> 
  type: T


/**
 * An Action type which accepts any other properties.
 * This is mainly for the use of the `Reducer` type.
 * This is not part of `Action` itself to prevent users who are extending `Action.
 */
export interface AnyAction extends Action 
  // Allows any extra properties to be defined in an action.
  [extraProps: string]: any

如何解决? 使用ThunkDispatch 类型而不是redux 的标准Dispatch。以下示例及更多内容可以在this Gist 上找到

const mapDispatchToProps = (dispatch: ThunkDispatch<MyState, void, Action>) => 
  return 
    onRequestClick: (arg: any) => dispatch(myAsyncAction(arg)),
  ;


另外,请参阅article,Map Dispatch to Props 部分

【讨论】:

感谢export function updateSession(loggedIn: UserSessionState) 的回答,但在这里我想说的是有效负载loggedIn 必须是UserSessionState 的形状,然后我就有了这里interface UpdateSessionAction type: 'USER_LOGIN'; payload: boolean; 的操作类型对吗? 谢谢!现在我得到Argument of type 'boolean' is not assignable to parameter of type 'UpdateSessionAction,但无论如何我都会接受你的回答,因为它是正确的。我需要了解更多关于 typescript 的知识,也许我把事情直接转移到异步操作中。 :)

以上是关于带有 Typescript 的 Redux Thunk的主要内容,如果未能解决你的问题,请参考以下文章

带有 Typescript 和 react-redux 的有状态组件:“typeof MyClass”类型的参数不可分配给 Component 类型的参数

react状态管理器(分模块)之redux和redux + react-redux + reducer和redux + react-redux + reducer分模块 + 异步操作redux-thu

如何将 Redux 4.0 TypeScript 绑定与 redux-thunk 一起使用

typescript + redux:在父组件中排除 redux props

Redux 的 combineReducers 和 TypeScript

typescript TypeScript中键入的Redux操作和Reducer的问题