Skip to content

Commit 62f341c

Browse files
authored
Merge pull request #2580 from reduxjs/feature/rtkq-pretyped-hooks
2 parents d0048ab + 2a66246 commit 62f341c

File tree

3 files changed

+130
-10
lines changed

3 files changed

+130
-10
lines changed

packages/toolkit/src/query/react/buildHooks.ts

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import { useStableQueryArgs } from './useSerializedStableValue'
5353
import type { UninitializedValue } from './constants'
5454
import { UNINITIALIZED_VALUE } from './constants'
5555
import { useShallowStableValue } from './useShallowStableValue'
56+
import type { BaseQueryFn } from '../baseQueryTypes'
5657

5758
// Copy-pasted from React-Redux
5859
export const useIsomorphicLayoutEffect =
@@ -98,7 +99,26 @@ export type UseQuery<D extends QueryDefinition<any, any, any, any>> = <
9899
>(
99100
arg: QueryArgFrom<D> | SkipToken,
100101
options?: UseQuerySubscriptionOptions & UseQueryStateOptions<D, R>
101-
) => UseQueryStateResult<D, R> & ReturnType<UseQuerySubscription<D>>
102+
) => UseQueryHookResult<D, R>
103+
104+
export type UseQueryHookResult<
105+
D extends QueryDefinition<any, any, any, any>,
106+
R = UseQueryStateDefaultResult<D>
107+
> = UseQueryStateResult<D, R> & UseQuerySubscriptionResult<D>
108+
109+
/**
110+
* Helper type to manually type the result
111+
* of the `useQuery` hook in userland code.
112+
*/
113+
export type TypedUseQueryHookResult<
114+
ResultType,
115+
QueryArg,
116+
BaseQuery extends BaseQueryFn,
117+
R = UseQueryStateDefaultResult<
118+
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>
119+
>
120+
> = TypedUseQueryStateResult<ResultType, QueryArg, BaseQuery, R> &
121+
TypedUseQuerySubscriptionResult<ResultType, QueryArg, BaseQuery>
102122

103123
interface UseQuerySubscriptionOptions extends SubscriptionOptions {
104124
/**
@@ -163,7 +183,23 @@ export type UseQuerySubscription<
163183
> = (
164184
arg: QueryArgFrom<D> | SkipToken,
165185
options?: UseQuerySubscriptionOptions
166-
) => Pick<QueryActionCreatorResult<D>, 'refetch'>
186+
) => UseQuerySubscriptionResult<D>
187+
188+
export type UseQuerySubscriptionResult<
189+
D extends QueryDefinition<any, any, any, any>
190+
> = Pick<QueryActionCreatorResult<D>, 'refetch'>
191+
192+
/**
193+
* Helper type to manually type the result
194+
* of the `useQuerySubscription` hook in userland code.
195+
*/
196+
export type TypedUseQuerySubscriptionResult<
197+
ResultType,
198+
QueryArg,
199+
BaseQuery extends BaseQueryFn
200+
> = UseQuerySubscriptionResult<
201+
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>
202+
>
167203

168204
export type UseLazyQueryLastPromiseInfo<
169205
D extends QueryDefinition<any, any, any, any>
@@ -339,6 +375,19 @@ export type UseQueryStateResult<
339375
R
340376
> = NoInfer<R>
341377

378+
/**
379+
* Helper type to manually type the result
380+
* of the `useQueryState` hook in userland code.
381+
*/
382+
export type TypedUseQueryStateResult<
383+
ResultType,
384+
QueryArg,
385+
BaseQuery extends BaseQueryFn,
386+
R = UseQueryStateDefaultResult<
387+
QueryDefinition<QueryArg, BaseQuery, string, ResultType, string>
388+
>
389+
> = NoInfer<R>
390+
342391
type UseQueryStateBaseResult<D extends QueryDefinition<any, any, any, any>> =
343392
QuerySubState<D> & {
344393
/**
@@ -436,6 +485,22 @@ export type UseMutationStateResult<
436485
reset: () => void
437486
}
438487

488+
/**
489+
* Helper type to manually type the result
490+
* of the `useMutation` hook in userland code.
491+
*/
492+
export type TypedUseMutationResult<
493+
ResultType,
494+
QueryArg,
495+
BaseQuery extends BaseQueryFn,
496+
R = MutationResultSelectorResult<
497+
MutationDefinition<QueryArg, BaseQuery, string, ResultType, string>
498+
>
499+
> = UseMutationStateResult<
500+
MutationDefinition<QueryArg, BaseQuery, string, ResultType, string>,
501+
R
502+
>
503+
439504
/**
440505
* A React hook that lets you trigger an update request for a given endpoint, and subscribes the component to read the request status from the Redux store. The component will re-render as the loading status changes.
441506
*

packages/toolkit/src/query/react/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,10 @@ const createApi = /* @__PURE__ */ buildCreateApi(
2121
reactHooksModule()
2222
)
2323

24+
export type {
25+
TypedUseQueryHookResult,
26+
TypedUseQueryStateResult,
27+
TypedUseQuerySubscriptionResult,
28+
TypedUseMutationResult,
29+
} from './buildHooks'
2430
export { createApi, reactHooksModule }

packages/toolkit/src/query/tests/unionTypes.test.ts

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
import type { SerializedError } from '@reduxjs/toolkit'
2-
import type { FetchBaseQueryError } from '@reduxjs/toolkit/query/react'
2+
import type {
3+
FetchBaseQueryError,
4+
TypedUseQueryHookResult,
5+
TypedUseQueryStateResult,
6+
TypedUseQuerySubscriptionResult,
7+
TypedUseMutationResult,
8+
} from '@reduxjs/toolkit/query/react'
39
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
410
import { expectExactType, expectType } from './helpers'
511

12+
const baseQuery = fetchBaseQuery()
613
const api = createApi({
7-
baseQuery: fetchBaseQuery(),
14+
baseQuery,
815
endpoints: (build) => ({
916
test: build.query<string, void>({ query: () => '' }),
1017
mutation: build.mutation<string, void>({ query: () => '' }),
@@ -141,7 +148,6 @@ describe.skip('TS only tests', () => {
141148
expectType<never>(result)
142149
}
143150
})
144-
// pre41-remove-start
145151
test('useQuery TS4.1 union', () => {
146152
const result = api.useTestQuery()
147153

@@ -207,7 +213,6 @@ describe.skip('TS only tests', () => {
207213
expectType<never>(result)
208214
}
209215
})
210-
// pre41-remove-end
211216

212217
test('useLazyQuery union', () => {
213218
const [_trigger, result] = api.endpoints.test.useLazyQuery()
@@ -275,7 +280,6 @@ describe.skip('TS only tests', () => {
275280
}
276281
})
277282

278-
// pre41-remove-start
279283
test('useLazyQuery TS4.1 union', () => {
280284
const [_trigger, result] = api.useLazyTestQuery()
281285

@@ -341,7 +345,6 @@ describe.skip('TS only tests', () => {
341345
expectType<never>(result)
342346
}
343347
})
344-
// pre41-remove-end
345348

346349
test('queryHookResult (without selector) union', () => {
347350
const useQueryStateResult = api.endpoints.test.useQueryState()
@@ -501,7 +504,6 @@ describe.skip('TS only tests', () => {
501504
})(result)
502505
})
503506

504-
// pre41-remove-start
505507
test('useMutation TS4.1 union', () => {
506508
const [_trigger, result] = api.useMutationMutation()
507509

@@ -552,5 +554,52 @@ describe.skip('TS only tests', () => {
552554
expectType<never>(result)
553555
}
554556
})
555-
// pre41-remove-end
557+
558+
test('"Typed" helper types', () => {
559+
// useQuery
560+
{
561+
const result = api.endpoints.test.useQuery()
562+
expectType<TypedUseQueryHookResult<string, void, typeof baseQuery>>(
563+
result
564+
)
565+
}
566+
// useQuery with selectFromResult
567+
{
568+
const result = api.endpoints.test.useQuery(undefined, {
569+
selectFromResult: () => ({ x: true }),
570+
})
571+
expectType<
572+
TypedUseQueryHookResult<string, void, typeof baseQuery, { x: boolean }>
573+
>(result)
574+
}
575+
// useQueryState
576+
{
577+
const result = api.endpoints.test.useQueryState()
578+
expectType<TypedUseQueryStateResult<string, void, typeof baseQuery>>(
579+
result
580+
)
581+
}
582+
// useQueryState with selectFromResult
583+
{
584+
const result = api.endpoints.test.useQueryState(undefined, {
585+
selectFromResult: () => ({ x: true }),
586+
})
587+
expectType<
588+
TypedUseQueryStateResult<string, void, typeof baseQuery, { x: boolean }>
589+
>(result)
590+
}
591+
// useQuerySubscription
592+
{
593+
const result = api.endpoints.test.useQuerySubscription()
594+
expectType<
595+
TypedUseQuerySubscriptionResult<string, void, typeof baseQuery>
596+
>(result)
597+
}
598+
599+
// useMutation
600+
{
601+
const [trigger, result] = api.endpoints.mutation.useMutation()
602+
expectType<TypedUseMutationResult<string, void, typeof baseQuery>>(result)
603+
}
604+
})
556605
})

0 commit comments

Comments
 (0)