【问题标题】:Redux Thunk with Typescript带有 Typescript 的 Redux Thunk
【发布时间】:2025-02-22 05:05:02
【问题描述】:

我正在学习 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';,我编辑了我的问题只是为了清楚起见,谢谢

标签: javascript reactjs typescript redux


【解决方案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)),
  };
}

另外,请参阅articleMap 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 的知识,也许我把事情直接转移到异步操作中。 :)