无法在createAsyncThunk中将getState类型设置为RootState

时间:2020-11-11 20:13:33

标签: typescript react-redux redux-thunk reduxjs-toolkit

我无法将getState()的返回类型设置为RootState。我正在使用打字稿和VS代码。我必须将类型设置为“ any”,这将在该对象上停止IntelliSense。下面是有问题的代码:

export const unsubscribeMeta = createAsyncThunk(
  'meta/unsubscribe',
  async (_, { getState }) => {
    const { meta } = getState() as any;
    const res = await client.post<apiUnsubscribeResponse>(
      `/meta/unsubscribe/${meta.subscriptionId}`
    );
    return res.data.data;
  }
);

如果我尝试使用“ RootState”而不是“ any”,则vscode在模块中标记了许多错误。我相信这是由于商店和切片之间存在循环依赖关系。我在选择器模块的更下方使用“ RootState”,这没有问题。有办法解决吗?

4 个答案:

答案 0 :(得分:6)

createAsyncThunk 可以具有在泛型上定义的类型:

export const unsubscribeMeta = createAsyncThunk<apiUnsubscribeResponse, void, {state: RootState }>(
  'meta/unsubscribe',
  async (_, { getState }) => {
    const { meta } = getState();
    const res = await client.post<apiUnsubscribeResponse>(
      `/meta/unsubscribe/${meta.subscriptionId}`
    );
    return res.data.data;
  }
);

定义 state 将自动使 getState 知道应用程序状态。

答案 1 :(得分:2)

您可以使用 Typescript 的 module augmentation 功能将默认状态分配给 AsyncThunkConfig.state,这将是我们稍后调用它时返回的 getState() 类型。

declare module "@reduxjs/toolkit" {
  type AsyncThunkConfig = {
    state?: unknown;
    dispatch?: Dispatch;
    extra?: unknown;
    rejectValue?: unknown;
    serializedErrorType?: unknown;
  };

  function createAsyncThunk<
    Returned,
    ThunkArg = void,
    ThunkApiConfig extends AsyncThunkConfig = {
      state: YourRootState; // this line makes a difference
    }
  >(
    typePrefix: string,
    payloadCreator: AsyncThunkPayloadCreator<
      Returned,
      ThunkArg,
      ThunkApiConfig
    >,
    options?: any
  ): AsyncThunk<Returned, ThunkArg, ThunkApiConfig>;
}

其中 YourRootState 是您商店状态的类型。

type YourRootState = {
  myNumber: number;
  myString: string;
};

现在您可以照常使用 createAsyncThunk 并且 getState() 返回正确的类型。

const doSomethingAsync = createAsyncThunk(
  "mySlice/action",
  async (_, { getState, dispatch }) => {
    const rootState = getState(); // has type YourRootState

    console.log(rootState.myNumber);
    console.log(rootState.myString);
  }
);


function Child() {
  const dispatch = useDispatch();
  return <button onClick={() => dispatch(doSomethingAsync())}>Click</button>;
}

现场演示

Edit 64793504/cannot-set-getstate-type-to-rootstate-in-createasyncthunk

答案 2 :(得分:1)

您实际上不需要了解整个状态的形状。您只需要了解要访问的值的存在。

如果您可以访问整个state.meta类型,则:

const { meta } = getState() as { meta: MetaState };

如果不是:

const { meta } = getState() as { meta: { subscriptionId: string } };

我建议使用这种方法来避免循环依赖,因为根状态始终取决于切片,因此切片不应依赖于根。

答案 3 :(得分:0)

仅从state: RootState类型中省略ThunkApiConfig,然后就可以在没有循环依赖关系的payloadCreator中使用const state = getState() as RootState;