Skip to content

Commit 22d0fbb

Browse files
authored
Merge pull request #1646 from reduxjs/expose-endpoint-types
2 parents b4e8d94 + 4862161 commit 22d0fbb

File tree

3 files changed

+103
-2
lines changed

3 files changed

+103
-2
lines changed

packages/toolkit/src/query/core/module.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,15 +320,25 @@ export interface ApiEndpointQuery<
320320
Definition extends QueryDefinition<any, any, any, any, any>,
321321
// eslint-disable-next-line @typescript-eslint/no-unused-vars
322322
Definitions extends EndpointDefinitions
323-
> {}
323+
> {
324+
/**
325+
* All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
326+
*/
327+
Types: NonNullable<Definition['Types']>
328+
}
324329

325330
// eslint-disable-next-line @typescript-eslint/no-unused-vars
326331
export interface ApiEndpointMutation<
327332
// eslint-disable-next-line @typescript-eslint/no-unused-vars
328333
Definition extends MutationDefinition<any, any, any, any, any>,
329334
// eslint-disable-next-line @typescript-eslint/no-unused-vars
330335
Definitions extends EndpointDefinitions
331-
> {}
336+
> {
337+
/**
338+
* All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
339+
*/
340+
Types: NonNullable<Definition['Types']>
341+
}
332342

333343
export type ListenerActions = {
334344
/**

packages/toolkit/src/query/endpointDefinitions.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,16 @@ interface EndpointDefinitionWithQueryFn<
154154
structuralSharing?: boolean
155155
}
156156

157+
export interface BaseEndpointTypes<
158+
QueryArg,
159+
BaseQuery extends BaseQueryFn,
160+
ResultType
161+
> {
162+
QueryArg: QueryArg
163+
BaseQuery: BaseQuery
164+
ResultType: ResultType
165+
}
166+
157167
export type BaseEndpointDefinition<
158168
QueryArg,
159169
BaseQuery extends BaseQueryFn,
@@ -221,6 +231,31 @@ export interface QueryApi<ReducerPath extends string, Context extends {}> {
221231
context: Context
222232
}
223233

234+
export interface QueryTypes<
235+
QueryArg,
236+
BaseQuery extends BaseQueryFn,
237+
TagTypes extends string,
238+
ResultType,
239+
ReducerPath extends string = string
240+
> extends BaseEndpointTypes<QueryArg, BaseQuery, ResultType> {
241+
/**
242+
* The endpoint definition type. To be used with some internal generic types.
243+
* @example
244+
* ```ts
245+
* const useMyWrappedHook: UseQuery<typeof api.endpoints.query.Types.QueryDefinition> = ...
246+
* ```
247+
*/
248+
QueryDefinition: QueryDefinition<
249+
QueryArg,
250+
BaseQuery,
251+
TagTypes,
252+
ResultType,
253+
ReducerPath
254+
>
255+
TagTypes: TagTypes
256+
ReducerPath: ReducerPath
257+
}
258+
224259
export interface QueryExtraOptions<
225260
TagTypes extends string,
226261
ResultType,
@@ -303,6 +338,11 @@ export interface QueryExtraOptions<
303338
currentCacheData: ResultType,
304339
responseData: ResultType
305340
): ResultType | void
341+
342+
/**
343+
* All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
344+
*/
345+
Types?: QueryTypes<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>
306346
}
307347

308348
export type QueryDefinition<
@@ -314,6 +354,31 @@ export type QueryDefinition<
314354
> = BaseEndpointDefinition<QueryArg, BaseQuery, ResultType> &
315355
QueryExtraOptions<TagTypes, ResultType, QueryArg, BaseQuery, ReducerPath>
316356

357+
export interface MutationTypes<
358+
QueryArg,
359+
BaseQuery extends BaseQueryFn,
360+
TagTypes extends string,
361+
ResultType,
362+
ReducerPath extends string = string
363+
> extends BaseEndpointTypes<QueryArg, BaseQuery, ResultType> {
364+
/**
365+
* The endpoint definition type. To be used with some internal generic types.
366+
* @example
367+
* ```ts
368+
* const useMyWrappedHook: UseMutation<typeof api.endpoints.query.Types.MutationDefinition> = ...
369+
* ```
370+
*/
371+
MutationDefinition: MutationDefinition<
372+
QueryArg,
373+
BaseQuery,
374+
TagTypes,
375+
ResultType,
376+
ReducerPath
377+
>
378+
TagTypes: TagTypes
379+
ReducerPath: ReducerPath
380+
}
381+
317382
export interface MutationExtraOptions<
318383
TagTypes extends string,
319384
ResultType,
@@ -378,6 +443,11 @@ export interface MutationExtraOptions<
378443
* Not to be used. A mutation should not provide tags to the cache.
379444
*/
380445
providesTags?: never
446+
447+
/**
448+
* All of these are `undefined` at runtime, purely to be used in TypeScript declarations!
449+
*/
450+
Types?: MutationTypes<QueryArg, BaseQuery, TagTypes, ResultType, ReducerPath>
381451
}
382452

383453
export type MutationDefinition<

packages/toolkit/src/query/tests/buildHooks.test.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import * as React from 'react'
2+
import type {
3+
UseMutation,
4+
UseQuery,
5+
} from '@reduxjs/toolkit/dist/query/react/buildHooks'
26
import {
37
createApi,
48
fetchBaseQuery,
@@ -2363,3 +2367,20 @@ describe('skip behaviour', () => {
23632367
expect(subscriptionCount('getUser(1)')).toBe(0)
23642368
})
23652369
})
2370+
2371+
// type tests:
2372+
{
2373+
const ANY = {} as any
2374+
2375+
// UseQuery type can be used to recreate the hook type
2376+
const fakeQuery = ANY as UseQuery<
2377+
typeof api.endpoints.getUser.Types.QueryDefinition
2378+
>
2379+
expectExactType(fakeQuery)(api.endpoints.getUser.useQuery)
2380+
2381+
// UseMutation type can be used to recreate the hook type
2382+
const fakeMutation = ANY as UseMutation<
2383+
typeof api.endpoints.updateUser.Types.MutationDefinition
2384+
>
2385+
expectExactType(fakeMutation)(api.endpoints.updateUser.useMutation)
2386+
}

0 commit comments

Comments
 (0)