Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TS error on injected API optimistic update #4471

Open
Onurfesci opened this issue Jun 20, 2024 · 5 comments
Open

TS error on injected API optimistic update #4471

Onurfesci opened this issue Jun 20, 2024 · 5 comments

Comments

@Onurfesci
Copy link

Onurfesci commented Jun 20, 2024

Hi, I'm getting a TS error when I try to use optimistic updates on a code-split API instance. The thunk works correctly and updates the data correctly, but TypeScript isn't happy. Here's the thunk:

    const dispatch = useAppDispatch();

    ...

    dispatch(
      beneficiariesApi.util.updateQueryData(
        'getBeneficiary',
        beneficiaryId,
        (draft) => {
          draft.data.attributes.trusted = true;
          return draft;
        }
      )
    );

TS error:

No overload matches this call.
  The last overload gave the following error.
    Argument of type 'ThunkAction<PatchCollection, RootState<UpdateDefinitions<{ getCountries: QueryDefinition<void, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, "ReferenceData", CountryPage, "api">; getCurrencies: QueryDefinition<...>; }, "ReferenceData" | ... 1 more ... | "Beneficiary", never> ...' is not assignable to parameter of type 'UnknownAction'.ts(2769)

I'm not sure what I'm doing wrong, as this endpoint is definitely defined within this set of endpoints.

@Onurfesci Onurfesci changed the title TS error on injected API util function TS error on injected API optimistic update Jun 20, 2024
@markerikson
Copy link
Collaborator

I see that you have set up a useAppDispatch hook per our recommendations. What is the TS-inferred type of dispatch at that point? Also, what does your store configuration look like?

@Onurfesci
Copy link
Author

Onurfesci commented Jun 20, 2024

Hi, the inferred type is:

(property) updateQueryData: <"getBeneficiary">(endpointName: "getBeneficiary", args: string, updateRecipe: Recipe<Beneficiary>, updateProvided?: boolean) => ThunkAction<PatchCollection, RootState<...>, any, UnknownAction>

The store config is:

import { configureStore } from '@reduxjs/toolkit';
// Or from '@reduxjs/toolkit/query/react'
import { setupListeners } from '@reduxjs/toolkit/query';

import { api } from './services/api';
import { registrationApi } from './services/registration';

export const store = configureStore({
  reducer: {
    // Add the generated reducer as a specific top-level slice
    [api.reducerPath]: api.reducer,
    [registrationApi.reducerPath]: registrationApi.reducer,
  },
  // Adding the api middleware enables caching, invalidation, polling,
  // and other useful features of `rtk-query`.
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat([api.middleware, registrationApi.middleware]),
});

// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>;
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;

// optional, but required for refetchOnFocus/refetchOnReconnect behaviors
// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization
setupListeners(store.dispatch);

And the beneficiariesApi is injected as:

import { api } from './api';

export const beneficiariesApi = api
  .enhanceEndpoints({
    addTagTypes: ['Beneficiaries', 'Beneficiary'],
  })
  .injectEndpoints({
    endpoints: (build) => ({
      ... endpoint definitions

Hope that helps :)

@markerikson
Copy link
Collaborator

markerikson commented Jun 20, 2024

Sorry, to clarify, what is the type of the dispatch function variable, and the AppDispatch type? Are they the same inferred type? Does the inferred type include a mention of "thunks" at all?

@Onurfesci
Copy link
Author

dispatch:

const dispatch: ThunkDispatch<{
    api: CombinedState<{
        getCountries: QueryDefinition<void, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, "ReferenceData", CountryPage, "api">;
        getCurrencies: QueryDefinition<...>;
    }, "ReferenceData", "api">;
    registrationApi: CombinedState<...>;
}, undefined, UnknownAction> & Dispatch<...>

AppDispatch:

type AppDispatch = ThunkDispatch<{
    api: CombinedState<{
        getCountries: QueryDefinition<void, BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError, {}, FetchBaseQueryMeta>, "ReferenceData", CountryPage, "api">;
        getCurrencies: QueryDefinition<...>;
    }, "ReferenceData", "api">;
    registrationApi: CombinedState<...>;
}, undefined, UnknownAction> & Dispatch<...>

Ah, it seems it doesn't have the injected endpoints

@markerikson
Copy link
Collaborator

Yeah, the API slice TS types only know about the endpoints in the original definition. someApi.injectEndpoints() then returns the same runtime object but with the additional TS types applied.

That said, the original error sounds more like "this typed version of dispatch doesn't know about thunks at all", but the inferred type does know about thunks, so I'm confused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants