当前位置: 首页 > 知识库问答 >
问题:

带有打字稿的Redux Thunk

史烨
2023-03-14

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

首先,我宣布会议状态

export interface UserSessionState {
  loggedIn: boolean;
}

然后我为这个动作声明接口

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

我使用联合类型导出它们

导出类型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 }));
};

在减速器中,我简单地初始化状态

初始状态: 用户会话状态 = {loggedIn: false}

然后我为减速机做正常的还原工作。

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

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'.

我缺少一个类型,但我不知道我做错了什么。


共有2个答案

井兴怀
2023-03-14

没有完全回答这个问题的相同问题,但我偶然发现了使用 Redux useDispatch() 钩子的相同问题。同样,对异步操作类型的支持也不太好。我最终做的是添加一个异步类型,并为键入创建了一个新的钩子:

// hooks.ts

export type AsyncAction = (dispatch: (action: Action) => any) => void;
export type Dispatcher = (action: AsyncAction | Action) => void
export const useAppDispatch: () => Dispatcher = useDispatch as any;

// async-actions.ts

import {AsyncAction} from "./hooks"

export const myAsyncAction: () => AsyncAction = () => (dispatch: (action: 
Action) => any) => {
// async logic with dispatching goes here:
// dispatch(...)
}

//my-component.tsx

import {myAsyncAction} from "./async-actions"
import {useAppDispatch} from "./hooks"

export const MyComponent = () => { 
  const dispatch = useAppDispatch();
  syncHandler () {
    disaptch ({type: MY_SYNC_ACTION})
  }
  asyncHandler () {
    disaptch (myAsyncAction())
  }
  ...
}

尽管有点Rescrep“hacky”,但这种方法的优点是您可以获得对同步和异步(Thunk)操作的完整类型检查支持,并且从客户端(组件)的角度来看没有区别 - 无需使用不同的类型系统

朱鹤轩
2023-03-14

总之:

您之所以会出现此错误,是因为从userLogin()函数返回的是一个ThunkAction

为什么会发生这种情况?

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

这是来自当前的 redux 类型文件

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
}

如何解决?使用“砰”类型,而不是“重复”的标准“派单”。以下示例和更多内容可以在此Gist上找到

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

另外,请参见本文的地图分派到道具一节

 类似资料:
  • 问题内容: 我们需要从Typescript中的node.js代码中调用REST API,并希望具有用于请求和响应的相应类型。不幸的是,给定接口的JSON包含以下字段: 我们被告知,这是由于另一端的自动化“ JSONifier”的局限性而无法更改的。我们如何设置适合于此的接口?以下显然不起作用: 问题答案: 就像JS对象一样,您可以用引号将名称引起来,如下所示:

  • 我试图在我的模型中添加一个静态方法,但是如果我这样做了,我得到了这个错误:< code >一个接口只能扩展一个类或另一个接口。 这是我的代码: 错误来自

  • 我正在努力寻找 有什么不同?

  • 我已经在我的.html文件中定义了这些: 然后在test.js: 但Typescript错误地指出:“找不到名称‘树’” 我也尝试编译与和放置在test.js文件的顶部,但它再次出错:

  • 问题内容: 我希望能够实例化一个Typescript类,在运行时可以获取该类和构造函数的详细信息。我想编写的函数将包含类名和构造函数参数。 问题答案: 您可以尝试: 编辑 此版本可在TypeScript操场上使用,例如:

  • typescript手册目前没有关于箭头功能的内容。普通函数可以使用以下语法进行一般类型化:示例: 箭头函数的语法是什么?