@reduxjs/toolkit
Version:
The official, opinionated, batteries-included toolset for efficient Redux development
1,117 lines (1,107 loc) • 138 kB
TypeScript
import * as _reduxjs_toolkit from '@reduxjs/toolkit';
import { ThunkDispatch, UnknownAction, Draft, AsyncThunk, SHOULD_AUTOBATCH, ThunkAction, SafePromise, SerializedError, PayloadAction, ActionCreatorWithoutPayload, Reducer, Middleware, ActionCreatorWithPayload, createSelector } from '@reduxjs/toolkit';
import { Patch } from 'immer';
import * as redux from 'redux';
import { StandardSchemaV1 } from '@standard-schema/spec';
import { SchemaError } from '@standard-schema/utils';
type Id<T> = {
[K in keyof T]: T[K];
} & {};
type WithRequiredProp<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
type Override<T1, T2> = T2 extends any ? Omit<T1, keyof T2> & T2 : never;
/**
* Convert a Union type `(A|B)` to an intersection type `(A&B)`
*/
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
type NonOptionalKeys<T> = {
[K in keyof T]-?: undefined extends T[K] ? never : K;
}[keyof T];
type HasRequiredProps<T, True, False> = NonOptionalKeys<T> extends never ? False : True;
type NoInfer<T> = [T][T extends any ? 0 : never];
type NonUndefined<T> = T extends undefined ? never : T;
type UnwrapPromise<T> = T extends PromiseLike<infer V> ? V : T;
type MaybePromise<T> = T | PromiseLike<T>;
type OmitFromUnion<T, K extends keyof T> = T extends any ? Omit<T, K> : never;
type IsAny<T, True, False = never> = true | false extends (T extends never ? true : false) ? True : False;
type CastAny<T, CastTo> = IsAny<T, CastTo, T>;
interface BaseQueryApi {
signal: AbortSignal;
abort: (reason?: string) => void;
dispatch: ThunkDispatch<any, any, any>;
getState: () => unknown;
extra: unknown;
endpoint: string;
type: 'query' | 'mutation';
/**
* Only available for queries: indicates if a query has been forced,
* i.e. it would have been fetched even if there would already be a cache entry
* (this does not mean that there is already a cache entry though!)
*
* This can be used to for example add a `Cache-Control: no-cache` header for
* invalidated queries.
*/
forced?: boolean;
/**
* Only available for queries: the cache key that was used to store the query result
*/
queryCacheKey?: string;
}
type QueryReturnValue<T = unknown, E = unknown, M = unknown> = {
error: E;
data?: undefined;
meta?: M;
} | {
error?: undefined;
data: T;
meta?: M;
};
type BaseQueryFn<Args = any, Result = unknown, Error = unknown, DefinitionExtraOptions = {}, Meta = {}> = (args: Args, api: BaseQueryApi, extraOptions: DefinitionExtraOptions) => MaybePromise<QueryReturnValue<Result, Error, Meta>>;
type BaseQueryEnhancer<AdditionalArgs = unknown, AdditionalDefinitionExtraOptions = unknown, Config = void> = <BaseQuery extends BaseQueryFn>(baseQuery: BaseQuery, config: Config) => BaseQueryFn<BaseQueryArg<BaseQuery> & AdditionalArgs, BaseQueryResult<BaseQuery>, BaseQueryError<BaseQuery>, BaseQueryExtraOptions<BaseQuery> & AdditionalDefinitionExtraOptions, NonNullable<BaseQueryMeta<BaseQuery>>>;
/**
* @public
*/
type BaseQueryResult<BaseQuery extends BaseQueryFn> = UnwrapPromise<ReturnType<BaseQuery>> extends infer Unwrapped ? Unwrapped extends {
data: any;
} ? Unwrapped['data'] : never : never;
/**
* @public
*/
type BaseQueryMeta<BaseQuery extends BaseQueryFn> = UnwrapPromise<ReturnType<BaseQuery>>['meta'];
/**
* @public
*/
type BaseQueryError<BaseQuery extends BaseQueryFn> = Exclude<UnwrapPromise<ReturnType<BaseQuery>>, {
error?: undefined;
}>['error'];
/**
* @public
*/
type BaseQueryArg<T extends (arg: any, ...args: any[]) => any> = T extends (arg: infer A, ...args: any[]) => any ? A : any;
/**
* @public
*/
type BaseQueryExtraOptions<BaseQuery extends BaseQueryFn> = Parameters<BaseQuery>[2];
declare const defaultSerializeQueryArgs: SerializeQueryArgs<any>;
type SerializeQueryArgs<QueryArgs, ReturnType = string> = (_: {
queryArgs: QueryArgs;
endpointDefinition: EndpointDefinition<any, any, any, any>;
endpointName: string;
}) => ReturnType;
type InternalSerializeQueryArgs = (_: {
queryArgs: any;
endpointDefinition: EndpointDefinition<any, any, any, any>;
endpointName: string;
}) => QueryCacheKey;
interface CreateApiOptions<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', TagTypes extends string = never> {
/**
* The base query used by each endpoint if no `queryFn` option is specified. RTK Query exports a utility called [fetchBaseQuery](./fetchBaseQuery) as a lightweight wrapper around `fetch` for common use-cases. See [Customizing Queries](../../rtk-query/usage/customizing-queries) if `fetchBaseQuery` does not handle your requirements.
*
* @example
*
* ```ts
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
*
* const api = createApi({
* // highlight-start
* baseQuery: fetchBaseQuery({ baseUrl: '/' }),
* // highlight-end
* endpoints: (build) => ({
* // ...endpoints
* }),
* })
* ```
*/
baseQuery: BaseQuery;
/**
* An array of string tag type names. Specifying tag types is optional, but you should define them so that they can be used for caching and invalidation. When defining a tag type, you will be able to [provide](../../rtk-query/usage/automated-refetching#providing-tags) them with `providesTags` and [invalidate](../../rtk-query/usage/automated-refetching#invalidating-tags) them with `invalidatesTags` when configuring [endpoints](#endpoints).
*
* @example
*
* ```ts
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
*
* const api = createApi({
* baseQuery: fetchBaseQuery({ baseUrl: '/' }),
* // highlight-start
* tagTypes: ['Post', 'User'],
* // highlight-end
* endpoints: (build) => ({
* // ...endpoints
* }),
* })
* ```
*/
tagTypes?: readonly TagTypes[];
/**
* The `reducerPath` is a _unique_ key that your service will be mounted to in your store. If you call `createApi` more than once in your application, you will need to provide a unique value each time. Defaults to `'api'`.
*
* @example
*
* ```ts
* // codeblock-meta title="apis.js"
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query';
*
* const apiOne = createApi({
* // highlight-start
* reducerPath: 'apiOne',
* // highlight-end
* baseQuery: fetchBaseQuery({ baseUrl: '/' }),
* endpoints: (builder) => ({
* // ...endpoints
* }),
* });
*
* const apiTwo = createApi({
* // highlight-start
* reducerPath: 'apiTwo',
* // highlight-end
* baseQuery: fetchBaseQuery({ baseUrl: '/' }),
* endpoints: (builder) => ({
* // ...endpoints
* }),
* });
* ```
*/
reducerPath?: ReducerPath;
/**
* Accepts a custom function if you have a need to change the creation of cache keys for any reason.
*/
serializeQueryArgs?: SerializeQueryArgs<unknown>;
/**
* Endpoints are a set of operations that you want to perform against your server. You define them as an object using the builder syntax. There are three endpoint types: [`query`](../../rtk-query/usage/queries), [`infiniteQuery`](../../rtk-query/usage/infinite-queries) and [`mutation`](../../rtk-query/usage/mutations).
*/
endpoints(build: EndpointBuilder<BaseQuery, TagTypes, ReducerPath>): Definitions;
/**
* Defaults to `60` _(this value is in seconds)_. This is how long RTK Query will keep your data cached for **after** the last component unsubscribes. For example, if you query an endpoint, then unmount the component, then mount another component that makes the same request within the given time frame, the most recent value will be served from the cache.
*
* ```ts
* // codeblock-meta title="keepUnusedDataFor example"
*
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
* interface Post {
* id: number
* name: string
* }
* type PostsResponse = Post[]
*
* const api = createApi({
* baseQuery: fetchBaseQuery({ baseUrl: '/' }),
* endpoints: (build) => ({
* getPosts: build.query<PostsResponse, void>({
* query: () => 'posts',
* // highlight-start
* keepUnusedDataFor: 5
* // highlight-end
* })
* })
* })
* ```
*/
keepUnusedDataFor?: number;
/**
* Defaults to `false`. This setting allows you to control whether if a cached result is already available RTK Query will only serve a cached result, or if it should `refetch` when set to `true` or if an adequate amount of time has passed since the last successful query result.
* - `false` - Will not cause a query to be performed _unless_ it does not exist yet.
* - `true` - Will always refetch when a new subscriber to a query is added. Behaves the same as calling the `refetch` callback or passing `forceRefetch: true` in the action creator.
* - `number` - **Value is in seconds**. If a number is provided and there is an existing query in the cache, it will compare the current time vs the last fulfilled timestamp, and only refetch if enough time has elapsed.
*
* If you specify this option alongside `skip: true`, this **will not be evaluated** until `skip` is false.
*/
refetchOnMountOrArgChange?: boolean | number;
/**
* Defaults to `false`. This setting allows you to control whether RTK Query will try to refetch all subscribed queries after the application window regains focus.
*
* If you specify this option alongside `skip: true`, this **will not be evaluated** until `skip` is false.
*
* Note: requires [`setupListeners`](./setupListeners) to have been called.
*/
refetchOnFocus?: boolean;
/**
* Defaults to `false`. This setting allows you to control whether RTK Query will try to refetch all subscribed queries after regaining a network connection.
*
* If you specify this option alongside `skip: true`, this **will not be evaluated** until `skip` is false.
*
* Note: requires [`setupListeners`](./setupListeners) to have been called.
*/
refetchOnReconnect?: boolean;
/**
* Defaults to `'delayed'`. This setting allows you to control when tags are invalidated after a mutation.
*
* - `'immediately'`: Queries are invalidated instantly after the mutation finished, even if they are running.
* If the query provides tags that were invalidated while it ran, it won't be re-fetched.
* - `'delayed'`: Invalidation only happens after all queries and mutations are settled.
* This ensures that queries are always invalidated correctly and automatically "batches" invalidations of concurrent mutations.
* Note that if you constantly have some queries (or mutations) running, this can delay tag invalidations indefinitely.
*/
invalidationBehavior?: 'delayed' | 'immediately';
/**
* A function that is passed every dispatched action. If this returns something other than `undefined`,
* that return value will be used to rehydrate fulfilled & errored queries.
*
* @example
*
* ```ts
* // codeblock-meta title="next-redux-wrapper rehydration example"
* import type { Action, PayloadAction } from '@reduxjs/toolkit'
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
* import { HYDRATE } from 'next-redux-wrapper'
*
* type RootState = any; // normally inferred from state
*
* function isHydrateAction(action: Action): action is PayloadAction<RootState> {
* return action.type === HYDRATE
* }
*
* export const api = createApi({
* baseQuery: fetchBaseQuery({ baseUrl: '/' }),
* // highlight-start
* extractRehydrationInfo(action, { reducerPath }): any {
* if (isHydrateAction(action)) {
* return action.payload[reducerPath]
* }
* },
* // highlight-end
* endpoints: (build) => ({
* // omitted
* }),
* })
* ```
*/
extractRehydrationInfo?: (action: UnknownAction, { reducerPath, }: {
reducerPath: ReducerPath;
}) => undefined | CombinedState<NoInfer<Definitions>, NoInfer<TagTypes>, NoInfer<ReducerPath>>;
/**
* A function that is called when a schema validation fails.
*
* Gets called with a `NamedSchemaError` and an object containing the endpoint name, the type of the endpoint, the argument passed to the endpoint, and the query cache key (if applicable).
*
* `NamedSchemaError` has the following properties:
* - `issues`: an array of issues that caused the validation to fail
* - `value`: the value that was passed to the schema
* - `schemaName`: the name of the schema that was used to validate the value (e.g. `argSchema`)
*
* @example
* ```ts
* // codeblock-meta no-transpile
* import { createApi } from '@reduxjs/toolkit/query/react'
* import * as v from "valibot"
*
* const api = createApi({
* baseQuery: fetchBaseQuery({ baseUrl: '/' }),
* endpoints: (build) => ({
* getPost: build.query<Post, { id: number }>({
* query: ({ id }) => `/post/${id}`,
* }),
* }),
* onSchemaFailure: (error, info) => {
* console.error(error, info)
* },
* })
* ```
*/
onSchemaFailure?: SchemaFailureHandler;
/**
* Convert a schema validation failure into an error shape matching base query errors.
*
* When not provided, schema failures are treated as fatal, and normal error handling such as tag invalidation will not be executed.
*
* @example
* ```ts
* // codeblock-meta no-transpile
* import { createApi } from '@reduxjs/toolkit/query/react'
* import * as v from "valibot"
*
* const api = createApi({
* baseQuery: fetchBaseQuery({ baseUrl: '/' }),
* endpoints: (build) => ({
* getPost: build.query<Post, { id: number }>({
* query: ({ id }) => `/post/${id}`,
* responseSchema: v.object({ id: v.number(), name: v.string() }),
* }),
* }),
* catchSchemaFailure: (error, info) => ({
* status: "CUSTOM_ERROR",
* error: error.schemaName + " failed validation",
* data: error.issues,
* }),
* })
* ```
*/
catchSchemaFailure?: SchemaFailureConverter<BaseQuery>;
/**
* Defaults to `false`.
*
* If set to `true`, will skip schema validation for all endpoints, unless overridden by the endpoint.
*
* @example
* ```ts
* // codeblock-meta no-transpile
* import { createApi } from '@reduxjs/toolkit/query/react'
* import * as v from "valibot"
*
* const api = createApi({
* baseQuery: fetchBaseQuery({ baseUrl: '/' }),
* skipSchemaValidation: process.env.NODE_ENV === "test", // skip schema validation in tests, since we'll be mocking the response
* endpoints: (build) => ({
* getPost: build.query<Post, { id: number }>({
* query: ({ id }) => `/post/${id}`,
* responseSchema: v.object({ id: v.number(), name: v.string() }),
* }),
* })
* })
* ```
*/
skipSchemaValidation?: boolean;
}
type CreateApi<Modules extends ModuleName> = {
/**
* Creates a service to use in your application. Contains only the basic redux logic (the core module).
*
* @link https://rtk-query-docs.netlify.app/api/createApi
*/
<BaseQuery extends BaseQueryFn, Definitions extends EndpointDefinitions, ReducerPath extends string = 'api', TagTypes extends string = never>(options: CreateApiOptions<BaseQuery, Definitions, ReducerPath, TagTypes>): Api<BaseQuery, Definitions, ReducerPath, TagTypes, Modules>;
};
/**
* Builds a `createApi` method based on the provided `modules`.
*
* @link https://rtk-query-docs.netlify.app/concepts/customizing-create-api
*
* @example
* ```ts
* const MyContext = React.createContext<ReactReduxContextValue | null>(null);
* const customCreateApi = buildCreateApi(
* coreModule(),
* reactHooksModule({
* hooks: {
* useDispatch: createDispatchHook(MyContext),
* useSelector: createSelectorHook(MyContext),
* useStore: createStoreHook(MyContext)
* }
* })
* );
* ```
*
* @param modules - A variable number of modules that customize how the `createApi` method handles endpoints
* @returns A `createApi` method using the provided `modules`.
*/
declare function buildCreateApi<Modules extends [Module<any>, ...Module<any>[]]>(...modules: Modules): CreateApi<Modules[number]['name']>;
type BuildThunksApiEndpointQuery<Definition extends QueryDefinition<any, any, any, any, any>> = Matchers<QueryThunk, Definition>;
type BuildThunksApiEndpointInfiniteQuery<Definition extends InfiniteQueryDefinition<any, any, any, any, any>> = Matchers<InfiniteQueryThunk<any>, Definition>;
type BuildThunksApiEndpointMutation<Definition extends MutationDefinition<any, any, any, any, any>> = Matchers<MutationThunk, Definition>;
type EndpointThunk<Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>, Definition extends EndpointDefinition<any, any, any, any>> = Definition extends EndpointDefinition<infer QueryArg, infer BaseQueryFn, any, infer ResultType> ? Thunk extends AsyncThunk<unknown, infer ATArg, infer ATConfig> ? AsyncThunk<ResultType, ATArg & {
originalArgs: QueryArg;
}, ATConfig & {
rejectValue: BaseQueryError<BaseQueryFn>;
}> : never : Definition extends InfiniteQueryDefinition<infer QueryArg, infer PageParam, infer BaseQueryFn, any, infer ResultType> ? Thunk extends AsyncThunk<unknown, infer ATArg, infer ATConfig> ? AsyncThunk<InfiniteData<ResultType, PageParam>, ATArg & {
originalArgs: QueryArg;
}, ATConfig & {
rejectValue: BaseQueryError<BaseQueryFn>;
}> : never : never;
type PendingAction<Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>, Definition extends EndpointDefinition<any, any, any, any>> = ReturnType<EndpointThunk<Thunk, Definition>['pending']>;
type FulfilledAction<Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>, Definition extends EndpointDefinition<any, any, any, any>> = ReturnType<EndpointThunk<Thunk, Definition>['fulfilled']>;
type RejectedAction<Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>, Definition extends EndpointDefinition<any, any, any, any>> = ReturnType<EndpointThunk<Thunk, Definition>['rejected']>;
type Matcher<M> = (value: any) => value is M;
interface Matchers<Thunk extends QueryThunk | MutationThunk | InfiniteQueryThunk<any>, Definition extends EndpointDefinition<any, any, any, any>> {
matchPending: Matcher<PendingAction<Thunk, Definition>>;
matchFulfilled: Matcher<FulfilledAction<Thunk, Definition>>;
matchRejected: Matcher<RejectedAction<Thunk, Definition>>;
}
type QueryThunkArg = QuerySubstateIdentifier & StartQueryActionCreatorOptions & {
type: 'query';
originalArgs: unknown;
endpointName: string;
};
type InfiniteQueryThunkArg<D extends InfiniteQueryDefinition<any, any, any, any, any>> = QuerySubstateIdentifier & StartInfiniteQueryActionCreatorOptions<D> & {
type: `query`;
originalArgs: unknown;
endpointName: string;
param: unknown;
direction?: InfiniteQueryDirection;
};
type MutationThunkArg = {
type: 'mutation';
originalArgs: unknown;
endpointName: string;
track?: boolean;
fixedCacheKey?: string;
};
type ThunkResult = unknown;
type ThunkApiMetaConfig = {
pendingMeta: {
startedTimeStamp: number;
[SHOULD_AUTOBATCH]: true;
};
fulfilledMeta: {
fulfilledTimeStamp: number;
baseQueryMeta: unknown;
[SHOULD_AUTOBATCH]: true;
};
rejectedMeta: {
baseQueryMeta: unknown;
[SHOULD_AUTOBATCH]: true;
};
};
type QueryThunk = AsyncThunk<ThunkResult, QueryThunkArg, ThunkApiMetaConfig>;
type InfiniteQueryThunk<D extends InfiniteQueryDefinition<any, any, any, any, any>> = AsyncThunk<ThunkResult, InfiniteQueryThunkArg<D>, ThunkApiMetaConfig>;
type MutationThunk = AsyncThunk<ThunkResult, MutationThunkArg, ThunkApiMetaConfig>;
type MaybeDrafted<T> = T | Draft<T>;
type Recipe<T> = (data: MaybeDrafted<T>) => void | MaybeDrafted<T>;
type PatchQueryDataThunk<Definitions extends EndpointDefinitions, PartialState> = <EndpointName extends QueryKeys<Definitions>>(endpointName: EndpointName, arg: QueryArgFrom<Definitions[EndpointName]>, patches: readonly Patch[], updateProvided?: boolean) => ThunkAction<void, PartialState, any, UnknownAction>;
type AllQueryKeys<Definitions extends EndpointDefinitions> = QueryKeys<Definitions> | InfiniteQueryKeys<Definitions>;
type QueryArgFromAnyQueryDefinition<Definitions extends EndpointDefinitions, EndpointName extends AllQueryKeys<Definitions>> = Definitions[EndpointName] extends InfiniteQueryDefinition<any, any, any, any, any> ? InfiniteQueryArgFrom<Definitions[EndpointName]> : Definitions[EndpointName] extends QueryDefinition<any, any, any, any> ? QueryArgFrom<Definitions[EndpointName]> : never;
type DataFromAnyQueryDefinition<Definitions extends EndpointDefinitions, EndpointName extends AllQueryKeys<Definitions>> = Definitions[EndpointName] extends InfiniteQueryDefinition<any, any, any, any, any> ? InfiniteData<ResultTypeFrom<Definitions[EndpointName]>, PageParamFrom<Definitions[EndpointName]>> : Definitions[EndpointName] extends QueryDefinition<any, any, any, any> ? ResultTypeFrom<Definitions[EndpointName]> : unknown;
type UpsertThunkResult<Definitions extends EndpointDefinitions, EndpointName extends AllQueryKeys<Definitions>> = Definitions[EndpointName] extends InfiniteQueryDefinition<any, any, any, any, any> ? InfiniteQueryActionCreatorResult<Definitions[EndpointName]> : Definitions[EndpointName] extends QueryDefinition<any, any, any, any> ? QueryActionCreatorResult<Definitions[EndpointName]> : QueryActionCreatorResult<never>;
type UpdateQueryDataThunk<Definitions extends EndpointDefinitions, PartialState> = <EndpointName extends AllQueryKeys<Definitions>>(endpointName: EndpointName, arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>, updateRecipe: Recipe<DataFromAnyQueryDefinition<Definitions, EndpointName>>, updateProvided?: boolean) => ThunkAction<PatchCollection, PartialState, any, UnknownAction>;
type UpsertQueryDataThunk<Definitions extends EndpointDefinitions, PartialState> = <EndpointName extends AllQueryKeys<Definitions>>(endpointName: EndpointName, arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>, value: DataFromAnyQueryDefinition<Definitions, EndpointName>) => ThunkAction<UpsertThunkResult<Definitions, EndpointName>, PartialState, any, UnknownAction>;
/**
* An object returned from dispatching a `api.util.updateQueryData` call.
*/
type PatchCollection = {
/**
* An `immer` Patch describing the cache update.
*/
patches: Patch[];
/**
* An `immer` Patch to revert the cache update.
*/
inversePatches: Patch[];
/**
* A function that will undo the cache update.
*/
undo: () => void;
};
type SkipToken = typeof skipToken;
/**
* Can be passed into `useQuery`, `useQueryState` or `useQuerySubscription`
* instead of the query argument to get the same effect as if setting
* `skip: true` in the query options.
*
* Useful for scenarios where a query should be skipped when `arg` is `undefined`
* and TypeScript complains about it because `arg` is not allowed to be passed
* in as `undefined`, such as
*
* ```ts
* // codeblock-meta title="will error if the query argument is not allowed to be undefined" no-transpile
* useSomeQuery(arg, { skip: !!arg })
* ```
*
* ```ts
* // codeblock-meta title="using skipToken instead" no-transpile
* useSomeQuery(arg ?? skipToken)
* ```
*
* If passed directly into a query or mutation selector, that selector will always
* return an uninitialized state.
*/
export declare const skipToken: unique symbol;
type BuildSelectorsApiEndpointQuery<Definition extends QueryDefinition<any, any, any, any, any>, Definitions extends EndpointDefinitions> = {
select: QueryResultSelectorFactory<Definition, RootState<Definitions, TagTypesFrom<Definition>, ReducerPathFrom<Definition>>>;
};
type BuildSelectorsApiEndpointInfiniteQuery<Definition extends InfiniteQueryDefinition<any, any, any, any, any>, Definitions extends EndpointDefinitions> = {
select: InfiniteQueryResultSelectorFactory<Definition, RootState<Definitions, TagTypesFrom<Definition>, ReducerPathFrom<Definition>>>;
};
type BuildSelectorsApiEndpointMutation<Definition extends MutationDefinition<any, any, any, any, any>, Definitions extends EndpointDefinitions> = {
select: MutationResultSelectorFactory<Definition, RootState<Definitions, TagTypesFrom<Definition>, ReducerPathFrom<Definition>>>;
};
type QueryResultSelectorFactory<Definition extends QueryDefinition<any, any, any, any>, RootState> = (queryArg: QueryArgFrom<Definition> | SkipToken) => (state: RootState) => QueryResultSelectorResult<Definition>;
type QueryResultSelectorResult<Definition extends QueryDefinition<any, any, any, any>> = QuerySubState<Definition> & RequestStatusFlags;
type InfiniteQueryResultSelectorFactory<Definition extends InfiniteQueryDefinition<any, any, any, any, any>, RootState> = (queryArg: InfiniteQueryArgFrom<Definition> | SkipToken) => (state: RootState) => InfiniteQueryResultSelectorResult<Definition>;
type InfiniteQueryResultFlags = {
hasNextPage: boolean;
hasPreviousPage: boolean;
isFetchingNextPage: boolean;
isFetchingPreviousPage: boolean;
isFetchNextPageError: boolean;
isFetchPreviousPageError: boolean;
};
type InfiniteQueryResultSelectorResult<Definition extends InfiniteQueryDefinition<any, any, any, any, any>> = InfiniteQuerySubState<Definition> & RequestStatusFlags & InfiniteQueryResultFlags;
type MutationResultSelectorFactory<Definition extends MutationDefinition<any, any, any, any>, RootState> = (requestId: string | {
requestId: string | undefined;
fixedCacheKey: string | undefined;
} | SkipToken) => (state: RootState) => MutationResultSelectorResult<Definition>;
type MutationResultSelectorResult<Definition extends MutationDefinition<any, any, any, any>> = MutationSubState<Definition> & RequestStatusFlags;
type BuildInitiateApiEndpointQuery<Definition extends QueryDefinition<any, any, any, any, any>> = {
initiate: StartQueryActionCreator<Definition>;
};
type BuildInitiateApiEndpointInfiniteQuery<Definition extends InfiniteQueryDefinition<any, any, any, any, any>> = {
initiate: StartInfiniteQueryActionCreator<Definition>;
};
type BuildInitiateApiEndpointMutation<Definition extends MutationDefinition<any, any, any, any, any>> = {
initiate: StartMutationActionCreator<Definition>;
};
declare const forceQueryFnSymbol: unique symbol;
type StartQueryActionCreatorOptions = {
subscribe?: boolean;
forceRefetch?: boolean | number;
subscriptionOptions?: SubscriptionOptions;
[forceQueryFnSymbol]?: () => QueryReturnValue;
};
type StartInfiniteQueryActionCreatorOptions<D extends InfiniteQueryDefinition<any, any, any, any, any>> = StartQueryActionCreatorOptions & {
direction?: InfiniteQueryDirection;
param?: unknown;
} & Partial<Pick<Partial<InfiniteQueryConfigOptions<ResultTypeFrom<D>, PageParamFrom<D>>>, 'initialPageParam'>>;
type StartQueryActionCreator<D extends QueryDefinition<any, any, any, any, any>> = (arg: QueryArgFrom<D>, options?: StartQueryActionCreatorOptions) => ThunkAction<QueryActionCreatorResult<D>, any, any, UnknownAction>;
type StartInfiniteQueryActionCreator<D extends InfiniteQueryDefinition<any, any, any, any, any>> = (arg: InfiniteQueryArgFrom<D>, options?: StartInfiniteQueryActionCreatorOptions<D>) => ThunkAction<InfiniteQueryActionCreatorResult<D>, any, any, UnknownAction>;
type QueryActionCreatorFields = {
requestId: string;
subscriptionOptions: SubscriptionOptions | undefined;
abort(): void;
unsubscribe(): void;
updateSubscriptionOptions(options: SubscriptionOptions): void;
queryCacheKey: string;
};
type QueryActionCreatorResult<D extends QueryDefinition<any, any, any, any>> = SafePromise<QueryResultSelectorResult<D>> & QueryActionCreatorFields & {
arg: QueryArgFrom<D>;
unwrap(): Promise<ResultTypeFrom<D>>;
refetch(): QueryActionCreatorResult<D>;
};
type InfiniteQueryActionCreatorResult<D extends InfiniteQueryDefinition<any, any, any, any, any>> = SafePromise<InfiniteQueryResultSelectorResult<D>> & QueryActionCreatorFields & {
arg: InfiniteQueryArgFrom<D>;
unwrap(): Promise<InfiniteData<ResultTypeFrom<D>, PageParamFrom<D>>>;
refetch(): InfiniteQueryActionCreatorResult<D>;
};
type StartMutationActionCreator<D extends MutationDefinition<any, any, any, any>> = (arg: QueryArgFrom<D>, options?: {
/**
* If this mutation should be tracked in the store.
* If you just want to manually trigger this mutation using `dispatch` and don't care about the
* result, state & potential errors being held in store, you can set this to false.
* (defaults to `true`)
*/
track?: boolean;
fixedCacheKey?: string;
}) => ThunkAction<MutationActionCreatorResult<D>, any, any, UnknownAction>;
type MutationActionCreatorResult<D extends MutationDefinition<any, any, any, any>> = SafePromise<{
data: ResultTypeFrom<D>;
error?: undefined;
} | {
data?: undefined;
error: Exclude<BaseQueryError<D extends MutationDefinition<any, infer BaseQuery, any, any> ? BaseQuery : never>, undefined> | SerializedError;
}> & {
/** @internal */
arg: {
/**
* The name of the given endpoint for the mutation
*/
endpointName: string;
/**
* The original arguments supplied to the mutation call
*/
originalArgs: QueryArgFrom<D>;
/**
* Whether the mutation is being tracked in the store.
*/
track?: boolean;
fixedCacheKey?: string;
};
/**
* A unique string generated for the request sequence
*/
requestId: string;
/**
* A method to cancel the mutation promise. Note that this is not intended to prevent the mutation
* that was fired off from reaching the server, but only to assist in handling the response.
*
* Calling `abort()` prior to the promise resolving will force it to reach the error state with
* the serialized error:
* `{ name: 'AbortError', message: 'Aborted' }`
*
* @example
* ```ts
* const [updateUser] = useUpdateUserMutation();
*
* useEffect(() => {
* const promise = updateUser(id);
* promise
* .unwrap()
* .catch((err) => {
* if (err.name === 'AbortError') return;
* // else handle the unexpected error
* })
*
* return () => {
* promise.abort();
* }
* }, [id, updateUser])
* ```
*/
abort(): void;
/**
* Unwraps a mutation call to provide the raw response/error.
*
* @remarks
* If you need to access the error or success payload immediately after a mutation, you can chain .unwrap().
*
* @example
* ```ts
* // codeblock-meta title="Using .unwrap"
* addPost({ id: 1, name: 'Example' })
* .unwrap()
* .then((payload) => console.log('fulfilled', payload))
* .catch((error) => console.error('rejected', error));
* ```
*
* @example
* ```ts
* // codeblock-meta title="Using .unwrap with async await"
* try {
* const payload = await addPost({ id: 1, name: 'Example' }).unwrap();
* console.log('fulfilled', payload)
* } catch (error) {
* console.error('rejected', error);
* }
* ```
*/
unwrap(): Promise<ResultTypeFrom<D>>;
/**
* A method to manually unsubscribe from the mutation call, meaning it will be removed from cache after the usual caching grace period.
The value returned by the hook will reset to `isUninitialized` afterwards.
*/
reset(): void;
};
type ReferenceCacheLifecycle = never;
interface QueryBaseLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> extends LifecycleApi<ReducerPath> {
/**
* Gets the current value of this cache entry.
*/
getCacheEntry(): QueryResultSelectorResult<{
type: DefinitionType.query;
} & BaseEndpointDefinition<QueryArg, BaseQuery, ResultType, BaseQueryResult<BaseQuery>>>;
/**
* Updates the current cache entry value.
* For documentation see `api.util.updateQueryData`.
*/
updateCachedData(updateRecipe: Recipe<ResultType>): PatchCollection;
}
type MutationBaseLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> = LifecycleApi<ReducerPath> & {
/**
* Gets the current value of this cache entry.
*/
getCacheEntry(): MutationResultSelectorResult<{
type: DefinitionType.mutation;
} & BaseEndpointDefinition<QueryArg, BaseQuery, ResultType, BaseQueryResult<BaseQuery>>>;
};
type LifecycleApi<ReducerPath extends string = string> = {
/**
* The dispatch method for the store
*/
dispatch: ThunkDispatch<any, any, UnknownAction>;
/**
* A method to get the current state
*/
getState(): RootState<any, any, ReducerPath>;
/**
* `extra` as provided as `thunk.extraArgument` to the `configureStore` `getDefaultMiddleware` option.
*/
extra: unknown;
/**
* A unique ID generated for the mutation
*/
requestId: string;
};
type CacheLifecyclePromises<ResultType = unknown, MetaType = unknown> = {
/**
* Promise that will resolve with the first value for this cache key.
* This allows you to `await` until an actual value is in cache.
*
* If the cache entry is removed from the cache before any value has ever
* been resolved, this Promise will reject with
* `new Error('Promise never resolved before cacheEntryRemoved.')`
* to prevent memory leaks.
* You can just re-throw that error (or not handle it at all) -
* it will be caught outside of `cacheEntryAdded`.
*
* If you don't interact with this promise, it will not throw.
*/
cacheDataLoaded: PromiseWithKnownReason<{
/**
* The (transformed) query result.
*/
data: ResultType;
/**
* The `meta` returned by the `baseQuery`
*/
meta: MetaType;
}, typeof neverResolvedError>;
/**
* Promise that allows you to wait for the point in time when the cache entry
* has been removed from the cache, by not being used/subscribed to any more
* in the application for too long or by dispatching `api.util.resetApiState`.
*/
cacheEntryRemoved: Promise<void>;
};
interface QueryCacheLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> extends QueryBaseLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>, CacheLifecyclePromises<ResultType, BaseQueryMeta<BaseQuery>> {
}
type MutationCacheLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> = MutationBaseLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath> & CacheLifecyclePromises<ResultType, BaseQueryMeta<BaseQuery>>;
type CacheLifecycleQueryExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = {
onCacheEntryAdded?(arg: QueryArg, api: QueryCacheLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>): Promise<void> | void;
};
type CacheLifecycleInfiniteQueryExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = CacheLifecycleQueryExtraOptions<ResultType, QueryArg, BaseQuery, ReducerPath>;
type CacheLifecycleMutationExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = {
onCacheEntryAdded?(arg: QueryArg, api: MutationCacheLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>): Promise<void> | void;
};
declare const neverResolvedError: Error & {
message: "Promise never resolved before cacheEntryRemoved.";
};
type ReferenceQueryLifecycle = never;
type QueryLifecyclePromises<ResultType, BaseQuery extends BaseQueryFn> = {
/**
* Promise that will resolve with the (transformed) query result.
*
* If the query fails, this promise will reject with the error.
*
* This allows you to `await` for the query to finish.
*
* If you don't interact with this promise, it will not throw.
*/
queryFulfilled: PromiseWithKnownReason<{
/**
* The (transformed) query result.
*/
data: ResultType;
/**
* The `meta` returned by the `baseQuery`
*/
meta: BaseQueryMeta<BaseQuery>;
}, QueryFulfilledRejectionReason<BaseQuery>>;
};
type QueryFulfilledRejectionReason<BaseQuery extends BaseQueryFn> = {
error: BaseQueryError<BaseQuery>;
/**
* If this is `false`, that means this error was returned from the `baseQuery` or `queryFn` in a controlled manner.
*/
isUnhandledError: false;
/**
* The `meta` returned by the `baseQuery`
*/
meta: BaseQueryMeta<BaseQuery>;
} | {
error: unknown;
meta?: undefined;
/**
* If this is `true`, that means that this error is the result of `baseQueryFn`, `queryFn`, `transformResponse` or `transformErrorResponse` throwing an error instead of handling it properly.
* There can not be made any assumption about the shape of `error`.
*/
isUnhandledError: true;
};
type QueryLifecycleQueryExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = {
/**
* A function that is called when the individual query is started. The function is called with a lifecycle api object containing properties such as `queryFulfilled`, allowing code to be run when a query is started, when it succeeds, and when it fails (i.e. throughout the lifecycle of an individual query/mutation call).
*
* Can be used to perform side-effects throughout the lifecycle of the query.
*
* @example
* ```ts
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
* import { messageCreated } from './notificationsSlice
* export interface Post {
* id: number
* name: string
* }
*
* const api = createApi({
* baseQuery: fetchBaseQuery({
* baseUrl: '/',
* }),
* endpoints: (build) => ({
* getPost: build.query<Post, number>({
* query: (id) => `post/${id}`,
* async onQueryStarted(id, { dispatch, queryFulfilled }) {
* // `onStart` side-effect
* dispatch(messageCreated('Fetching posts...'))
* try {
* const { data } = await queryFulfilled
* // `onSuccess` side-effect
* dispatch(messageCreated('Posts received!'))
* } catch (err) {
* // `onError` side-effect
* dispatch(messageCreated('Error fetching posts!'))
* }
* }
* }),
* }),
* })
* ```
*/
onQueryStarted?(queryArgument: QueryArg, queryLifeCycleApi: QueryLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>): Promise<void> | void;
};
type QueryLifecycleInfiniteQueryExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = QueryLifecycleQueryExtraOptions<ResultType, QueryArg, BaseQuery, ReducerPath>;
type QueryLifecycleMutationExtraOptions<ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> = {
/**
* A function that is called when the individual mutation is started. The function is called with a lifecycle api object containing properties such as `queryFulfilled`, allowing code to be run when a query is started, when it succeeds, and when it fails (i.e. throughout the lifecycle of an individual query/mutation call).
*
* Can be used for `optimistic updates`.
*
* @example
*
* ```ts
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
* export interface Post {
* id: number
* name: string
* }
*
* const api = createApi({
* baseQuery: fetchBaseQuery({
* baseUrl: '/',
* }),
* tagTypes: ['Post'],
* endpoints: (build) => ({
* getPost: build.query<Post, number>({
* query: (id) => `post/${id}`,
* providesTags: ['Post'],
* }),
* updatePost: build.mutation<void, Pick<Post, 'id'> & Partial<Post>>({
* query: ({ id, ...patch }) => ({
* url: `post/${id}`,
* method: 'PATCH',
* body: patch,
* }),
* invalidatesTags: ['Post'],
* async onQueryStarted({ id, ...patch }, { dispatch, queryFulfilled }) {
* const patchResult = dispatch(
* api.util.updateQueryData('getPost', id, (draft) => {
* Object.assign(draft, patch)
* })
* )
* try {
* await queryFulfilled
* } catch {
* patchResult.undo()
* }
* },
* }),
* }),
* })
* ```
*/
onQueryStarted?(queryArgument: QueryArg, mutationLifeCycleApi: MutationLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>): Promise<void> | void;
};
interface QueryLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> extends QueryBaseLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath>, QueryLifecyclePromises<ResultType, BaseQuery> {
}
type MutationLifecycleApi<QueryArg, BaseQuery extends BaseQueryFn, ResultType, ReducerPath extends string = string> = MutationBaseLifecycleApi<QueryArg, BaseQuery, ResultType, ReducerPath> & QueryLifecyclePromises<ResultType, BaseQuery>;
/**
* Provides a way to define a strongly-typed version of
* {@linkcode QueryLifecycleQueryExtraOptions.onQueryStarted | onQueryStarted}
* for a specific query.
*
* @example
* <caption>#### __Create and reuse a strongly-typed `onQueryStarted` function__</caption>
*
* ```ts
* import type { TypedQueryOnQueryStarted } from '@reduxjs/toolkit/query'
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
*
* type Post = {
* id: number
* title: string
* userId: number
* }
*
* type PostsApiResponse = {
* posts: Post[]
* total: number
* skip: number
* limit: number
* }
*
* type QueryArgument = number | undefined
*
* type BaseQueryFunction = ReturnType<typeof fetchBaseQuery>
*
* const baseApiSlice = createApi({
* baseQuery: fetchBaseQuery({ baseUrl: 'https://dummyjson.com' }),
* reducerPath: 'postsApi',
* tagTypes: ['Posts'],
* endpoints: (build) => ({
* getPosts: build.query<PostsApiResponse, void>({
* query: () => `/posts`,
* }),
*
* getPostById: build.query<Post, QueryArgument>({
* query: (postId) => `/posts/${postId}`,
* }),
* }),
* })
*
* const updatePostOnFulfilled: TypedQueryOnQueryStarted<
* PostsApiResponse,
* QueryArgument,
* BaseQueryFunction,
* 'postsApi'
* > = async (queryArgument, { dispatch, queryFulfilled }) => {
* const result = await queryFulfilled
*
* const { posts } = result.data
*
* // Pre-fill the individual post entries with the results
* // from the list endpoint query
* dispatch(
* baseApiSlice.util.upsertQueryEntries(
* posts.map((post) => ({
* endpointName: 'getPostById',
* arg: post.id,
* value: post,
* })),
* ),
* )
* }
*
* export const extendedApiSlice = baseApiSlice.injectEndpoints({
* endpoints: (build) => ({
* getPostsByUserId: build.query<PostsApiResponse, QueryArgument>({
* query: (userId) => `/posts/user/${userId}`,
*
* onQueryStarted: updatePostOnFulfilled,
* }),
* }),
* })
* ```
*
* @template ResultType - The type of the result `data` returned by the query.
* @template QueryArgumentType - The type of the argument passed into the query.
* @template BaseQueryFunctionType - The type of the base query function being used.
* @template ReducerPath - The type representing the `reducerPath` for the API slice.
*
* @since 2.4.0
* @public
*/
type TypedQueryOnQueryStarted<ResultType, QueryArgumentType, BaseQueryFunctionType extends BaseQueryFn, ReducerPath extends string = string> = QueryLifecycleQueryExtraOptions<ResultType, QueryArgumentType, BaseQueryFunctionType, ReducerPath>['onQueryStarted'];
/**
* Provides a way to define a strongly-typed version of
* {@linkcode QueryLifecycleMutationExtraOptions.onQueryStarted | onQueryStarted}
* for a specific mutation.
*
* @example
* <caption>#### __Create and reuse a strongly-typed `onQueryStarted` function__</caption>
*
* ```ts
* import type { TypedMutationOnQueryStarted } from '@reduxjs/toolkit/query'
* import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
*
* type Post = {
* id: number
* title: string
* userId: number
* }
*
* type PostsApiResponse = {
* posts: Post[]
* total: number
* skip: number
* limit: number
* }
*
* type QueryArgument = Pick<Post, 'id'> & Partial<Post>
*
* type BaseQueryFunction = ReturnType<typeof fetchBaseQuery>
*
* const baseApiSlice = createApi({
* baseQuery: fetchBaseQuery({ baseUrl: 'https://dummyjson.com' }),
* reducerPath: 'postsApi',
* tagTypes: ['Posts'],
* endpoints: (build) => ({
* getPosts: build.query<PostsApiResponse, void>({
* query: () => `/posts`,
* }),
*
* getPostById: build.query<Post, number>({
* query: (postId) => `/posts/${postId}`,
* }),
* }),
* })
*
* const updatePostOnFulfilled: TypedMutationOnQueryStarted<
* Post,
* QueryArgument,
* BaseQueryFunction,
* 'postsApi'
* > = async ({ id, ...patch }, { dispatch, queryFulfilled }) => {
* const patchCollection = dispatch(
* baseApiSlice.util.updateQueryData('getPostById', id, (draftPost) => {
* Object.assign(draftPost, patch)
* }),
* )
*
* try {
* await queryFulfilled
* } catch {
* patchCollection.undo()
* }
* }
*
* export const extendedApiSlice = baseApiSlice.injectEndpoints({
* endpoints: (build) => ({
* addPost: build.mutation<Post, Omit<QueryArgument, 'id'>>({
* query: (body) => ({
* url: `posts/add`,
* method: 'POST',
* body,
* }),
*
* onQueryStarted: updatePostOnFulfilled,
* }),
*
* updatePost: build.mutation<Post, QueryArgument>({
* query: ({ id, ...patch }) => ({
* url: `post/${id}`,
* method: 'PATCH',
* body: patch,
* }),
*
* onQueryStarted: updatePostOnFulfilled,
* }),
* }),
* })
* ```
*
* @template ResultType - The type of the result `data` returned by the query.
* @template QueryArgumentType - The type of the argument passed into the query.
* @template BaseQueryFunctionType - The type of the base query function being used.
* @template ReducerPath - The type representing the `reducerPath` for the API slice.
*
* @since 2.4.0
* @public
*/
type TypedMutationOnQueryStarted<ResultType, QueryArgumentType, BaseQueryFunctionType extends BaseQueryFn, ReducerPath extends string = string> = QueryLifecycleMutationExtraOptions<ResultType, QueryArgumentType, BaseQueryFunctionType, ReducerPath>['onQueryStarted'];
/**
* A typesafe single entry to be upserted into the cache
*/
type NormalizedQueryUpsertEntry<Definitions extends EndpointDefinitions, EndpointName extends AllQueryKeys<Definitions>> = {
endpointName: EndpointName;
arg: QueryArgFromAnyQueryDefinition<Definitions, EndpointName>;
value: DataFromAnyQueryDefinition<Definitions, EndpointName>;
};
/**
* The internal version that is not typesafe since we can't carry the generics through `createSlice`
*/
type NormalizedQueryUpsertEntryPayload = {
endpointName: string;
arg: unknown;
value: unknown;
};
type ProcessedQueryUpsertEntry = {
queryDescription: QueryThunkArg;
value: unknown;
};
/**
* A typesafe representation of a util action creator that accepts cache entry descriptions to upsert
*/
type UpsertEntries<Definitions extends EndpointDefinitions> = (<EndpointNames extends Array<AllQueryKeys<Definitions>>>(entries: [
...{
[I in keyof EndpointNames]: NormalizedQueryUpsertEntry<Definitions, EndpointNames[I]>;
}
]) => PayloadAction<NormalizedQueryUpsertEntryPayload[]>) & {
match: (action: unknown) => action is PayloadAction<NormalizedQueryUpsertEntryPayload[]>;
};
declare function buildSlice({ reducerPath, queryThunk, mutationThunk, serializeQueryArgs, context: { endpointDefinitions: definitions, apiUid, extractRehydrationInfo, hasRehydrationInfo, }, assertTagType, config, }: {
reducerPath: string;
queryThunk: QueryThunk;
infiniteQueryThunk: InfiniteQueryThunk<any>;
mutationThunk: MutationThunk;
serializeQueryArgs: InternalSerializeQueryArgs;
context: ApiContext<EndpointDefinitions>;
assertTagType: AssertTagTypes;
config: Omit<ConfigState<string>, 'online' | 'focused' | 'middlewareRegistered'>;
}): {
reducer: redux.Reducer<{
queries: QueryState<any>;
mutat