使用自定义类型的 useAppDispatch 挂钩时,获取“类型为 'AsyncThunkAction<*> 的参数不可分配给类型为'Action<any>”的参数

Posted

技术标签:

【中文标题】使用自定义类型的 useAppDispatch 挂钩时,获取“类型为 \'AsyncThunkAction<*> 的参数不可分配给类型为\'Action<any>”的参数【英文标题】:Getting "Argument of type 'AsyncThunkAction<*> is not assignable to parameter of type 'Action<any>" when using custom typed useAppDispatch hook使用自定义类型的 useAppDispatch 挂钩时,获取“类型为 'AsyncThunkAction<*> 的参数不可分配给类型为'Action<any>”的参数 【发布时间】:2021-07-07 13:46:59 【问题描述】:

this link 中的一个工作示例。

我开始使用 TypeScript 和 Redux Toolkit 开发 React 应用程序。我按照 Redux Toolkit 文档中关于如何将它与 TypeScript 一起使用的说明进行操作。所以,我输入了StateRootState 类型)和 Dispatch(AppDispatch 类型)的版本

export const store = configureStore(
  reducer: 
    information: informationReducer,
  ,
);

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch; 

另外,我正在尝试使用appDispatch (useAppDispatch) 的类型化版本。

export const useAppDispatch = (): ReturnType<typeof useDispatch> =>
  useDispatch<AppDispatch>();

问题是我收到一个错误提示

“AsyncThunkAction”类型的参数不能分配给“Action”类型的参数

当使用 useAppDispatch 的返回调用异步 thunk 时:

export const Information: React.FunctionComponent = () => 
  const appDispatch = useAppDispatch();
  useEffect(() => 
    appDispatch(fetchInformation()); // error occurs here
  );

  return <p>An awesome information component</p>;
;

我的 thunk 是使用 createAsyncThunk 创建的:

type ThunkAPi = 
    rejectValue: string;
;

export const fetchInformation = createAsyncThunk<string, void, ThunkAPi>(
    "information/fetchInformation",
    async (_, thunkAPi) => 
        const result = Math.floor(Math.random() * 10);
        if (result > 3) 
            return Promise.resolve("resolved");
        

        return thunkAPi.rejectWithValue("rejected");
    
);

我不知道为什么,但是当我删除useAppDispatch 的类型时,错误消失了。也就是这样使用:

export const useAppDispatch = () => useDispatch<AppDispatch>();

代替:

export const useAppDispatch = (): ReturnType<typeof useDispatch> =>
      useDispatch<AppDispatch>();

此外,当我使用标准挂钩 useDispatch 而不是自定义类型的 useAppDispatch 时,错误消失了。

所以,我的问题是:为什么会出现这个错误?似乎我所有的类型系统都是正确的......我寻找了类似的问题,但没有发现任何可以解决我的问题。

感谢您的帮助。

【问题讨论】:

【参考方案1】:

正如在 https://redux.js.org/recipes/usage-with-typescript#define-typed-hooks 中特别记录的那样,正确的定义是:

import  TypedUseSelectorHook, useDispatch, useSelector  from 'react-redux'
import type  RootState, AppDispatch  from './store'

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

您的示例说它返回“useDispatch 的返回类型”,这是普通的未增强/非 thunk-aware Dispatch 类型。那肯定行不通。

不确定您为什么要尝试为 useAppDispatch 做一些不同的事情 - 请使用此处显示的正确定义。

【讨论】:

嗨@mar​​kerikson。谢谢您的帮助!那么,您是说没有办法为useAppDispatch 定义类型吗?我只是想为它定义一个类型,因为我更喜欢使用显式函数返回类型并启用了 eslint 规则@typescript-eslint/explicit-function-return-type 该类型将是 () =&gt; AppDispatch - 但是很多 RTK 的创建方式是您不应该特别手动为其分配类型,因为您将丢失有价值的类型信息并获得低于标准的开发以这种方式体验。

以上是关于使用自定义类型的 useAppDispatch 挂钩时,获取“类型为 'AsyncThunkAction<*> 的参数不可分配给类型为'Action<any>”的参数的主要内容,如果未能解决你的问题,请参考以下文章

ERP中通过自定义单打开流程图

金蝶K3Cloud单据挂起怎么处理

将 UIViewController 推送到 UINavigationController 时动画挂起

从Gradle生命周期到自定义Task挂接到Build构建流程全解

从Gradle生命周期到自定义Task挂接到Build构建流程全解

以编程方式将自定义范围添加到Azure B2C