redux 如何用泛型异步thunk作为参数输入函数?

pzfprimi  于 2023-02-04  发布在  其他
关注(0)|答案(1)|浏览(185)

我无法获得正确的类型来将异步thunk作为函数的参数传递,也无法传播其3个关联的泛型类型,以便在调用函数时可以推断出它们。
我在文档中找不到任何关于如何处理这一问题的配方或解释。撇开打字不谈,下面的示例在应用程序中按预期工作(公司代码,无法共享)。
我的具体用例是我想要一个函数,它接受两个thunk,并创建一个新的thunk来调度这两个thunk,组合参数。

const chainAsyncThunks = <
  FirstReturned,
  FirstThunkArg,
  FirstThunkApiConfig extends {},
  SecondReturned,
  SecondThunkArg,
  SecondThunkApiConfig extends {},
>(
  prefix: string,
  thunk1: AsyncThunk<FirstReturned, FirstThunkArg, FirstThunkApiConfig>,
  thunk2: AsyncThunk<SecondReturned, SecondThunkArg, SecondThunkApiConfig>,
) => {
  return createAsyncThunk('chained/' + prefix, async (arg: FirstThunkArg & SecondThunkArg, thunkAPI) => {
    const initialState = thunkAPI.getState() as RootState;
    try {
      await thunkAPI.dispatch(thunk1(arg)).unwrap();
    } catch (rejectedResult) {
      thunkAPI.dispatch(setRootState(initialState));
      throw rejectedResult;
    }
    try {
      await thunkAPI.dispatch(thunk2(arg)).unwrap();
    } catch (rejectedResult) {
      thunkAPI.dispatch(setRootState(initialState));
      throw rejectedResult;
    }
  });
};

我得到了一个很长的,看起来无法读取的错误。

TS2769: No overload matches this call.
  Overload 1 of 3, '(thunkAction: ThunkAction<Promise<PayloadAction<FirstReturned, string, { arg: FirstThunkArg; requestId: string;
 requestStatus: "fulfilled"; }, never> | PayloadAction<...>> & { ...; }, unknown, unknown, AnyAction>): Promise<...> & { ...; }', gave the following error.
    Argument of type 'AsyncThunkAction<FirstReturned, FirstThunkArg, FirstThunkApiConfig>' is not assignable to parameter of type '
ThunkAction<Promise<PayloadAction<FirstReturned, string, { arg: FirstThunkArg; requestId: string; requestStatus: "fulfilled"; }, ne
ver> | PayloadAction<GetRejectValue<...> | undefined, string, { ...; } & (({ ...; } & { [K in keyof GetRejectedMeta<...>]?: undefined; }) | ({ ...; } & GetRejectedMeta<...>)), GetSeriali...'.
      Types of parameters 'dispatch' and 'dispatch' are incompatible.
        Type 'ThunkDispatch<unknown, unknown, AnyAction>' is not assignable to type 'GetDispatch<FirstThunkApiConfig>'.
  Overload 2 of 3, '(action: AnyAction): AnyAction', gave the following error.
    Argument of type 'AsyncThunkAction<FirstReturned, FirstThunkArg, FirstThunkApiConfig>' is not assignable to parameter of type 'AnyAction'.
  Overload 3 of 3, '(action: AnyAction | ThunkAction<Promise<PayloadAction<FirstReturned, string, { arg: FirstThunkArg; requestId: 
string; requestStatus: "fulfilled"; }, never> | PayloadAction<...>> & { ...; }, unknown, unknown, AnyAction>): AnyAction | (Promise<...> & { ...; })', gave the following error.
    Argument of type 'AsyncThunkAction<FirstReturned, FirstThunkArg, FirstThunkApiConfig>' is not assignable to parameter of type '
AnyAction | ThunkAction<Promise<PayloadAction<FirstReturned, string, { arg: FirstThunkArg; requestId: string; requestStatus: "fulfilled"; }, never> | PayloadAction<...>> & { ...; }, unknown, unknown, AnyAction>'.
      Type 'AsyncThunkAction<FirstReturned, FirstThunkArg, FirstThunkApiConfig>' is not assignable to type 'ThunkAction<Promise<Pay
loadAction<FirstReturned, string, { arg: FirstThunkArg; requestId: string; requestStatus: "fulfilled"; }, never> | PayloadAction<Ge
tRejectValue<...> | undefined, string, { ...; } & (({ ...; } & { [K in keyof GetRejectedMeta<...>]?: undefined; }) | ({ ...; } & GetRejectedMeta<...>)), GetSeriali...'.
    19 |     const initialState = thunkAPI.getState() as RootState;
    20 |     try {
  > 21 |       await thunkAPI.dispatch(thunk1(arg)).unwrap();
      Type 'AsyncThunkAction<SecondReturned, SecondThunkArg, SecondThunkApiConfig>' is not assignable to type 'ThunkAction<Promise<PayloadAction<SecondReturned, string, { arg: SecondThunkArg; requestId: string; requestStatus: "fulfilled"; }, never> | PayloadAction<...>> & { ...; }, unknown, unknown, AnyAction>'.
    25 |     }
    26 |     try {
  > 27 |       await thunkAPI.dispatch(thunk2(arg)).unwrap();
       |                               ^^^^^^^^^^^
    28 |     } catch (rejectedResult) {
    29 |       thunkAPI.dispatch(setRootState(initialState));
    30 |       throw rejectedResult;
zf9nrax1

zf9nrax11#

是否有理由必须是asyncThunk?意思是:您是否对要调度的组合thunk的pending/fulfilled/rejected操作感兴趣?
如果没有,就编写一个普通的thunk函数:

import { ThunkDispatch, AnyAction } from '@reduxjs/toolkit'

function buildCombinedThunk<Arg>(thunk1: (arg: Arg) => ThunkAction<{unwrap: () => Promise<any>}, RootState, unknown, AnyAction>, thunk2: (arg: Arg) => ThunkAction<{unwrap: () => Promise<any>}, RootState, unknown, AnyAction>) {
  return (arg: Arg) => async (dispatch: ThunkDispatch<unknown, unknown, AnyAction>, getState: () => RootState) => {
    const initialState = getState();
    try {
      await dispatch(thunk1(arg)).unwrap();
    } catch (rejectedResult) {
      dispatch(setRootState(initialState));
      throw rejectedResult;
    }
    try {
      await dispatch(thunk2(arg)).unwrap();
    } catch (rejectedResult) {
      dispatch(setRootState(initialState));
      throw rejectedResult;
    }

  }
}

一般来说:这样编写高阶函数可能是绝对的矫枉过正,当你真正需要它们的时候,编写这些组合的thunk可能是一个更好的主意--这样你就可以编写更“合适”的逻辑,而不是通用的逻辑。

相关问题