Redux-toolkit: ThunkApi.getState with Typescript

Created on 5 Nov 2020  路  7Comments  路  Source: reduxjs/redux-toolkit

Hi everyone!
How I can get rid of the following TS error?

export const getSibling = createAsyncThunk<
{response: Data},
{id: string},
{getState: () => RootState}
>(`Tree_data/fetch_sibling`, async({id}, thunkApi) => {
const {tree: {treeData}} = thunkApi.getState()

// omitted code
}

const RootState = ReturnType<typeof store.getState> exported from index.ts

In the snippet above TS shows an error : Type { omitted for brevity} has no properties in common with 'AsyncThunkConfig' for the {getState: () => RootState} line

Due to limitations of working machine the snippet was re-typed by hand, I hope that it will be enough. Thanks

Most helpful comment

almost there ;)

export const getSibling = createAsyncThunk<
{response: Data},
{id: string},
-{getState: () => RootState}
+{state: RootState}
>(`Tree_data/fetch_sibling`, async({id}, thunkApi) => {
const {tree: {treeData}} = thunkApi.getState()

// omitted code
}

All 7 comments

almost there ;)

export const getSibling = createAsyncThunk<
{response: Data},
{id: string},
-{getState: () => RootState}
+{state: RootState}
>(`Tree_data/fetch_sibling`, async({id}, thunkApi) => {
const {tree: {treeData}} = thunkApi.getState()

// omitted code
}

The generic argument for the return type of payloadCreator can be inferred from the code and the type of the root state is always the same, so both are actually unnecessary from a human perspective.
Ideally, I could write code like this:

export const getSibling = createAsyncThunk<{id: string}>(`Tree_data/fetch_sibling`, async({id}, thunkApi) => {/*...*/});
// or
export const getSibling = createAsyncThunk(`Tree_data/fetch_sibling`, async({id}: {id: string}, thunkApi) => {/*...*/});

It would mean that I would need to create an alias for createAsyncThunk, but that's not easily possible because not all types used in the function signature are exported. The culprit is the type of the options parameter AsyncThunkOptions.

Any ideas how to create an alias without rebuilding the complete type definitions in my own code?

@dhilgarth https://github.com/reduxjs/redux-toolkit/pull/684 would give you tools to do that, but at the current point we are not sure if that's worth the extra ceremony to actually do that.

Generally speaking, this is a TypeScript problem: we cannot mix inferred and explicit generic arguments.
https://github.com/microsoft/TypeScript/pull/26349 would allow that and then you could do

export const getSibling = createAsyncThunk<_,  _, AsyncThunkConfig>( ... )

where the _ usages will be inferred, but until that is merged, you are pretty much out of luck.

Thanks for the extremely quick response on a Sunday!

It would help if you could export AsyncThunkOptions. That would allow to do this:

export function createAsyncThunk<Returned, ThunkArg = void>(typePrefix: string, payloadCreator: AsyncThunkPayloadCreator<Returned, ThunkArg, {state: AppState}>, options?: AsyncThunkOptions<ThunkArg, {state: AppState}>): AsyncThunk<Returned, ThunkArg, {state: AppState}>
{
    return rtk.createAsyncThunk(typePrefix, payloadCreator, options)
}

Yeah, I think we can do that in a future version.

Awesome! Should I create another issue specifically for that? With this issue being closed and broader?

I'll just do a small PR later.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

denu5 picture denu5  路  4Comments

ouweiya picture ouweiya  路  3Comments

nonissue picture nonissue  路  3Comments

Izhaki picture Izhaki  路  3Comments

FdezRomero picture FdezRomero  路  4Comments