UNPKG

@reduxjs/toolkit

Version:

The official, opinionated, batteries-included toolset for efficient Redux development

289 lines (288 loc) 15 kB
import type { AnyAction, ThunkDispatch } from '@reduxjs/toolkit'; import type { RootState } from './core/apiState'; import type { BaseQueryExtraOptions, BaseQueryFn, BaseQueryResult, BaseQueryArg, BaseQueryApi, QueryReturnValue, BaseQueryError, BaseQueryMeta } from './baseQueryTypes'; import type { HasRequiredProps, MaybePromise, OmitFromUnion, CastAny } from './tsHelpers'; import type { NEVER } from './fakeBaseQuery'; declare const resultType: unique symbol; declare const baseQuery: unique symbol; interface EndpointDefinitionWithQuery<QueryArg, BaseQuery extends BaseQueryFn, ResultType> { /** * `query` can be a function that returns either a `string` or an `object` which is passed to your `baseQuery`. If you are using [fetchBaseQuery](./fetchBaseQuery), this can return either a `string` or an `object` of properties in `FetchArgs`. If you use your own custom [`baseQuery`](../../rtk-query/usage/customizing-queries), you can customize this behavior to your liking. * * @example * * ```ts * // codeblock-meta title="query 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>({ * // highlight-start * query: () => 'posts', * // highlight-end * }) * }) * }) * ``` */ query(arg: QueryArg): BaseQueryArg<BaseQuery>; queryFn?: never; /** * A function to manipulate the data returned by a query or mutation. */ transformResponse?(baseQueryReturnValue: BaseQueryResult<BaseQuery>, meta: BaseQueryMeta<BaseQuery>): ResultType | Promise<ResultType>; } interface EndpointDefinitionWithQueryFn<QueryArg, BaseQuery extends BaseQueryFn, ResultType> { /** * Can be used in place of `query` as an inline function that bypasses `baseQuery` completely for the endpoint. * * @example * ```ts * // codeblock-meta title="Basic queryFn 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', * }), * flipCoin: build.query<'heads' | 'tails', void>({ * // highlight-start * queryFn(arg, queryApi, extraOptions, baseQuery) { * const randomVal = Math.random() * if (randomVal < 0.45) { * return { data: 'heads' } * } * if (randomVal < 0.9) { * return { data: 'tails' } * } * return { error: { status: 500, statusText: 'Internal Server Error', data: "Coin landed on it's edge!" } } * } * // highlight-end * }) * }) * }) * ``` */ queryFn(arg: QueryArg, api: BaseQueryApi, extraOptions: BaseQueryExtraOptions<BaseQuery>, baseQuery: (arg: Parameters<BaseQuery>[0]) => ReturnType<BaseQuery>): MaybePromise<QueryReturnValue<ResultType, BaseQueryError<BaseQuery>>>; query?: never; transformResponse?: never; } export declare type BaseEndpointDefinition<QueryArg, BaseQuery extends BaseQueryFn, ResultType> = (([CastAny<BaseQueryResult<BaseQuery>, {}>] extends [NEVER] ? never : EndpointDefinitionWithQuery<QueryArg, BaseQuery, ResultType>) | EndpointDefinitionWithQueryFn<QueryArg, BaseQuery, ResultType>) & { [resultType]?: ResultType; [baseQuery]?: BaseQuery; } & HasRequiredProps<BaseQueryExtraOptions<BaseQuery>, { extraOptions: BaseQueryExtraOptions<BaseQuery>; }, { extraOptions?: BaseQueryExtraOptions<BaseQuery>; }>; export declare enum DefinitionType { query = "query", mutation = "mutation" } export declare type GetResultDescriptionFn<TagTypes extends string, ResultType, QueryArg, ErrorType> = (result: ResultType | undefined, error: ErrorType | undefined, arg: QueryArg) => ReadonlyArray<TagDescription<TagTypes>>; export declare type FullTagDescription<TagType> = { type: TagType; id?: number | string; }; export declare type TagDescription<TagType> = TagType | FullTagDescription<TagType>; export declare type ResultDescription<TagTypes extends string, ResultType, QueryArg, ErrorType> = ReadonlyArray<TagDescription<TagTypes>> | GetResultDescriptionFn<TagTypes, ResultType, QueryArg, ErrorType>; /** @deprecated please use `onQueryStarted` instead */ export interface QueryApi<ReducerPath extends string, Context extends {}> { /** @deprecated please use `onQueryStarted` instead */ dispatch: ThunkDispatch<any, any, AnyAction>; /** @deprecated please use `onQueryStarted` instead */ getState(): RootState<any, any, ReducerPath>; /** @deprecated please use `onQueryStarted` instead */ extra: unknown; /** @deprecated please use `onQueryStarted` instead */ requestId: string; /** @deprecated please use `onQueryStarted` instead */ context: Context; } export interface QueryExtraOptions<TagTypes extends string, ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> { type: DefinitionType.query; /** * Used by `query` endpoints. Determines which 'tag' is attached to the cached data returned by the query. * Expects an array of tag type strings, an array of objects of tag types with ids, or a function that returns such an array. * 1. `['Post']` - equivalent to `2` * 2. `[{ type: 'Post' }]` - equivalent to `1` * 3. `[{ type: 'Post', id: 1 }]` * 4. `(result, error, arg) => ['Post']` - equivalent to `5` * 5. `(result, error, arg) => [{ type: 'Post' }]` - equivalent to `4` * 6. `(result, error, arg) => [{ type: 'Post', id: 1 }]` * * @example * * ```ts * // codeblock-meta title="providesTags example" * * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' * interface Post { * id: number * name: string * } * type PostsResponse = Post[] * * const api = createApi({ * baseQuery: fetchBaseQuery({ baseUrl: '/' }), * tagTypes: ['Posts'], * endpoints: (build) => ({ * getPosts: build.query<PostsResponse, void>({ * query: () => 'posts', * // highlight-start * providesTags: (result) => * result * ? [ * ...result.map(({ id }) => ({ type: 'Posts' as const, id })), * { type: 'Posts', id: 'LIST' }, * ] * : [{ type: 'Posts', id: 'LIST' }], * // highlight-end * }) * }) * }) * ``` */ providesTags?: ResultDescription<TagTypes, ResultType, QueryArg, BaseQueryError<BaseQuery>>; /** * Not to be used. A query should not invalidate tags in the cache. */ invalidatesTags?: never; } export declare type QueryDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & QueryExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath>; export interface MutationExtraOptions<TagTypes extends string, ResultType, QueryArg, BaseQuery extends BaseQueryFn, ReducerPath extends string = string> { type: DefinitionType.mutation; /** * Used by `mutation` endpoints. Determines which cached data should be either re-fetched or removed from the cache. * Expects the same shapes as `providesTags`. * * @example * * ```ts * // codeblock-meta title="invalidatesTags example" * import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' * interface Post { * id: number * name: string * } * type PostsResponse = Post[] * * const api = createApi({ * baseQuery: fetchBaseQuery({ baseUrl: '/' }), * tagTypes: ['Posts'], * endpoints: (build) => ({ * getPosts: build.query<PostsResponse, void>({ * query: () => 'posts', * providesTags: (result) => * result * ? [ * ...result.map(({ id }) => ({ type: 'Posts' as const, id })), * { type: 'Posts', id: 'LIST' }, * ] * : [{ type: 'Posts', id: 'LIST' }], * }), * addPost: build.mutation<Post, Partial<Post>>({ * query(body) { * return { * url: `posts`, * method: 'POST', * body, * } * }, * // highlight-start * invalidatesTags: [{ type: 'Posts', id: 'LIST' }], * // highlight-end * }), * }) * }) * ``` */ invalidatesTags?: ResultDescription<TagTypes, ResultType, QueryArg, BaseQueryError<BaseQuery>>; /** * Not to be used. A mutation should not provide tags to the cache. */ providesTags?: never; } export declare type MutationDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> & MutationExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath>; export declare type EndpointDefinition<QueryArg, BaseQuery extends BaseQueryFn, TagTypes extends string, ResultType, ReducerPath extends string = string> = QueryDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath> | MutationDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>; export declare type EndpointDefinitions = Record<string, EndpointDefinition<any, any, any, any>>; export declare function isQueryDefinition(e: EndpointDefinition<any, any, any, any>): e is QueryDefinition<any, any, any, any>; export declare function isMutationDefinition(e: EndpointDefinition<any, any, any, any>): e is MutationDefinition<any, any, any, any>; export declare type EndpointBuilder<BaseQuery extends BaseQueryFn, TagTypes extends string, ReducerPath extends string> = { /** * An endpoint definition that retrieves data, and may provide tags to the cache. * * @example * ```js * // codeblock-meta title="Example of all query endpoint options" * const api = createApi({ * baseQuery, * endpoints: (build) => ({ * getPost: build.query({ * query: (id) => ({ url: `post/${id}` }), * // Pick out data and prevent nested properties in a hook or selector * transformResponse: (response) => response.data, * // `result` is the server response * providesTags: (result, error, id) => [{ type: 'Post', id }], * // trigger side effects or optimistic updates * onQueryStarted(id, { dispatch, getState, extra, requestId, queryFulfilled, getCacheEntry, updateCachedData }) {}, * // handle subscriptions etc * onCacheEntryAdded(id, { dispatch, getState, extra, requestId, cacheEntryRemoved, cacheDataLoaded, getCacheEntry, updateCachedData }) {}, * }), * }), *}); *``` */ query<ResultType, QueryArg>(definition: OmitFromUnion<QueryDefinition<QueryArg, BaseQuery, TagTypes, ResultType>, 'type'>): QueryDefinition<QueryArg, BaseQuery, TagTypes, ResultType>; /** * An endpoint definition that alters data on the server or will possibly invalidate the cache. * * @example * ```js * // codeblock-meta title="Example of all mutation endpoint options" * const api = createApi({ * baseQuery, * endpoints: (build) => ({ * updatePost: build.mutation({ * query: ({ id, ...patch }) => ({ url: `post/${id}`, method: 'PATCH', body: patch }), * // Pick out data and prevent nested properties in a hook or selector * transformResponse: (response) => response.data, * // `result` is the server response * invalidatesTags: (result, error, id) => [{ type: 'Post', id }], * // trigger side effects or optimistic updates * onQueryStarted(id, { dispatch, getState, extra, requestId, queryFulfilled, getCacheEntry }) {}, * // handle subscriptions etc * onCacheEntryAdded(id, { dispatch, getState, extra, requestId, cacheEntryRemoved, cacheDataLoaded, getCacheEntry }) {}, * }), * }), * }); * ``` */ mutation<ResultType, QueryArg>(definition: OmitFromUnion<MutationDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>, 'type'>): MutationDefinition<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>; }; export declare type AssertTagTypes = <T extends FullTagDescription<string>>(t: T) => T; export declare function calculateProvidedBy<ResultType, QueryArg, ErrorType>(description: ResultDescription<string, ResultType, QueryArg, ErrorType> | undefined, result: ResultType | undefined, error: ErrorType | undefined, queryArg: QueryArg, assertTagTypes: AssertTagTypes): readonly FullTagDescription<string>[]; export declare type QueryArgFrom<D extends BaseEndpointDefinition<any, any, any>> = D extends BaseEndpointDefinition<infer QA, any, any> ? QA : unknown; export declare type ResultTypeFrom<D extends BaseEndpointDefinition<any, any, any>> = D extends BaseEndpointDefinition<any, any, infer RT> ? RT : unknown; export declare type ReducerPathFrom<D extends EndpointDefinition<any, any, any, any>> = D extends EndpointDefinition<any, any, any, infer RP> ? RP : unknown; export declare type TagTypesFrom<D extends EndpointDefinition<any, any, any, any>> = D extends EndpointDefinition<any, any, infer RP, any> ? RP : unknown; export declare type ReplaceTagTypes<Definitions extends EndpointDefinitions, NewTagTypes extends string> = { [K in keyof Definitions]: Definitions[K] extends QueryDefinition<infer QueryArg, infer BaseQuery, any, infer ResultType, infer ReducerPath> ? QueryDefinition<QueryArg, BaseQuery, NewTagTypes, ResultType, ReducerPath> : Definitions[K] extends MutationDefinition<infer QueryArg, infer BaseQuery, any, infer ResultType, infer ReducerPath> ? MutationDefinition<QueryArg, BaseQuery, NewTagTypes, ResultType, ReducerPath> : never; }; export {};