Skip to content

Commit 4989399

Browse files
Nick-LucasTkDodo
andauthored
fix(types): fix issues with queryOptions factory method types (#8394)
* Fix issues with queryOptions factory method types * Apply the same fixes to infiniteQueryOptions * Revert change to failing test * Fix test in more userland way * Unused import * Add tRPC-style solution * Unused import --------- Co-authored-by: Dominik Dorfmeister <[email protected]>
1 parent 4521a04 commit 4989399

File tree

8 files changed

+124
-23
lines changed

8 files changed

+124
-23
lines changed

packages/query-core/src/__tests__/queryClient.test-d.tsx

+2-7
Original file line numberDiff line numberDiff line change
@@ -228,16 +228,11 @@ describe('fully typed usage', () => {
228228
TData,
229229
TError,
230230
TData,
231-
QueryKey & DataTag<unknown, TData, TError>
231+
DataTag<QueryKey, TData, TError>
232232
> = {
233233
predicate(query) {
234234
expectTypeOf(query).toEqualTypeOf<
235-
Query<
236-
TData,
237-
TError,
238-
TData,
239-
QueryKey & DataTag<unknown, TData, TError>
240-
>
235+
Query<TData, TError, TData, DataTag<QueryKey, TData, TError>>
241236
>()
242237
expectTypeOf(query.state.data).toEqualTypeOf<TData | undefined>()
243238
expectTypeOf(query.state.error).toEqualTypeOf<TError | null>()

packages/query-core/src/__tests__/utils.test-d.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ describe('QueryFilters', () => {
1111
TData,
1212
Error,
1313
TData,
14-
QueryKey & DataTag<unknown, TData>
14+
DataTag<QueryKey, TData>
1515
> = {
1616
predicate(query) {
1717
expectTypeOf(query.setData({ a: 1, b: '1' })).toEqualTypeOf<TData>()
@@ -37,7 +37,7 @@ describe('QueryFilters', () => {
3737
TData,
3838
TError,
3939
TData,
40-
QueryKey & DataTag<unknown, TData, TError>
40+
DataTag<QueryKey, TData, TError>
4141
> = {
4242
predicate(query) {
4343
expectTypeOf(query.setData({ a: 1, b: '1' })).toEqualTypeOf<TData>()

packages/query-core/src/types.ts

+13-3
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,20 @@ export declare const dataTagSymbol: unique symbol
4646
export declare const dataTagErrorSymbol: unique symbol
4747
export declare const unsetMarker: unique symbol
4848
export type UnsetMarker = typeof unsetMarker
49-
export type DataTag<TType, TValue, TError = UnsetMarker> = TType & {
50-
[dataTagSymbol]: TValue
51-
[dataTagErrorSymbol]: TError
49+
export type AnyDataTag = {
50+
[dataTagSymbol]: any
51+
[dataTagErrorSymbol]: any
5252
}
53+
export type DataTag<
54+
TType,
55+
TValue,
56+
TError = UnsetMarker,
57+
> = TType extends AnyDataTag
58+
? TType
59+
: TType & {
60+
[dataTagSymbol]: TValue
61+
[dataTagErrorSymbol]: TError
62+
}
5363

5464
export type QueryFunction<
5565
T = unknown,

packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx

+39-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ import { infiniteQueryOptions } from '../infiniteQueryOptions'
44
import { useInfiniteQuery } from '../useInfiniteQuery'
55
import { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery'
66
import { useQuery } from '../useQuery'
7-
import type { InfiniteData, InitialDataFunction } from '@tanstack/query-core'
7+
import type {
8+
DataTag,
9+
InfiniteData,
10+
InitialDataFunction,
11+
} from '@tanstack/query-core'
812

913
describe('infiniteQueryOptions', () => {
1014
it('should not allow excess properties', () => {
@@ -200,4 +204,38 @@ describe('infiniteQueryOptions', () => {
200204
| undefined
201205
>()
202206
})
207+
208+
it('should return a custom query key type', () => {
209+
type MyQueryKey = [Array<string>, { type: 'foo' }]
210+
211+
const options = infiniteQueryOptions({
212+
queryKey: [['key'], { type: 'foo' }] as MyQueryKey,
213+
queryFn: () => Promise.resolve(1),
214+
getNextPageParam: () => 1,
215+
initialPageParam: 1,
216+
})
217+
218+
expectTypeOf(options.queryKey).toEqualTypeOf<
219+
DataTag<MyQueryKey, InfiniteData<number>, Error>
220+
>()
221+
})
222+
223+
it('should return a custom query key type with datatag', () => {
224+
type MyQueryKey = DataTag<
225+
[Array<string>, { type: 'foo' }],
226+
number,
227+
Error & { myMessage: string }
228+
>
229+
230+
const options = infiniteQueryOptions({
231+
queryKey: [['key'], { type: 'foo' }] as MyQueryKey,
232+
queryFn: () => Promise.resolve(1),
233+
getNextPageParam: () => 1,
234+
initialPageParam: 1,
235+
})
236+
237+
expectTypeOf(options.queryKey).toEqualTypeOf<
238+
DataTag<MyQueryKey, InfiniteData<number>, Error & { myMessage: string }>
239+
>()
240+
})
203241
})

packages/react-query/src/__tests__/queryOptions.test-d.tsx

+35-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import { queryOptions } from '../queryOptions'
99
import { useQuery } from '../useQuery'
1010
import { useQueries } from '../useQueries'
1111
import { useSuspenseQuery } from '../useSuspenseQuery'
12-
import type { UseQueryOptions } from '../types'
12+
import type { AnyUseQueryOptions } from '../types'
1313
import type {
14+
DataTag,
1415
InitialDataFunction,
1516
QueryObserverResult,
1617
} from '@tanstack/query-core'
@@ -236,7 +237,9 @@ describe('queryOptions', () => {
236237
})
237238

238239
it('should be passable to UseQueryOptions', () => {
239-
function somethingWithQueryOptions(options: UseQueryOptions<number>) {
240+
function somethingWithQueryOptions<TQueryOpts extends AnyUseQueryOptions>(
241+
options: TQueryOpts,
242+
) {
240243
return options.queryKey
241244
}
242245

@@ -247,4 +250,34 @@ describe('queryOptions', () => {
247250

248251
somethingWithQueryOptions(options)
249252
})
253+
254+
it('should return a custom query key type', () => {
255+
type MyQueryKey = [Array<string>, { type: 'foo' }]
256+
257+
const options = queryOptions({
258+
queryKey: [['key'], { type: 'foo' }] as MyQueryKey,
259+
queryFn: () => Promise.resolve(1),
260+
})
261+
262+
expectTypeOf(options.queryKey).toEqualTypeOf<
263+
DataTag<MyQueryKey, number, Error>
264+
>()
265+
})
266+
267+
it('should return a custom query key type with datatag', () => {
268+
type MyQueryKey = DataTag<
269+
[Array<string>, { type: 'foo' }],
270+
number,
271+
Error & { myMessage: string }
272+
>
273+
274+
const options = queryOptions({
275+
queryKey: [['key'], { type: 'foo' }] as MyQueryKey,
276+
queryFn: () => Promise.resolve(1),
277+
})
278+
279+
expectTypeOf(options.queryKey).toEqualTypeOf<
280+
DataTag<MyQueryKey, number, Error & { myMessage: string }>
281+
>()
282+
})
250283
})

packages/react-query/src/infiniteQueryOptions.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export function infiniteQueryOptions<
104104
TQueryKey,
105105
TPageParam
106106
> & {
107-
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>>
107+
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
108108
}
109109

110110
export function infiniteQueryOptions<
@@ -128,7 +128,7 @@ export function infiniteQueryOptions<
128128
TQueryKey,
129129
TPageParam
130130
> & {
131-
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>>
131+
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
132132
}
133133

134134
export function infiniteQueryOptions<
@@ -152,7 +152,7 @@ export function infiniteQueryOptions<
152152
TQueryKey,
153153
TPageParam
154154
> & {
155-
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>>
155+
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
156156
}
157157

158158
export function infiniteQueryOptions(options: unknown) {

packages/react-query/src/queryOptions.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ export function queryOptions<
5555
TQueryKey extends QueryKey = QueryKey,
5656
>(
5757
options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,
58-
): DefinedInitialDataOptions<TQueryFnData, TError, TData> & {
59-
queryKey: DataTag<QueryKey, TQueryFnData>
58+
): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {
59+
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
6060
}
6161

6262
export function queryOptions<
@@ -66,8 +66,8 @@ export function queryOptions<
6666
TQueryKey extends QueryKey = QueryKey,
6767
>(
6868
options: UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey>,
69-
): UnusedSkipTokenOptions<TQueryFnData, TError, TData> & {
70-
queryKey: DataTag<QueryKey, TQueryFnData>
69+
): UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> & {
70+
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
7171
}
7272

7373
export function queryOptions<
@@ -78,7 +78,7 @@ export function queryOptions<
7878
>(
7979
options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,
8080
): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {
81-
queryKey: DataTag<TQueryKey, TQueryFnData>
81+
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
8282
}
8383

8484
export function queryOptions(options: unknown) {

packages/react-query/src/types.ts

+25
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ import type {
1717
SkipToken,
1818
} from '@tanstack/query-core'
1919

20+
export type AnyUseBaseQueryOptions = UseBaseQueryOptions<
21+
any,
22+
any,
23+
any,
24+
any,
25+
any
26+
>
2027
export interface UseBaseQueryOptions<
2128
TQueryFnData = unknown,
2229
TError = DefaultError,
@@ -31,6 +38,7 @@ export interface UseBaseQueryOptions<
3138
TQueryKey
3239
> {}
3340

41+
export type AnyUseQueryOptions = UseQueryOptions<any, any, any, any>
3442
export interface UseQueryOptions<
3543
TQueryFnData = unknown,
3644
TError = DefaultError,
@@ -41,6 +49,12 @@ export interface UseQueryOptions<
4149
'suspense'
4250
> {}
4351

52+
export type AnyUseSuspenseQueryOptions = UseSuspenseQueryOptions<
53+
any,
54+
any,
55+
any,
56+
any
57+
>
4458
export interface UseSuspenseQueryOptions<
4559
TQueryFnData = unknown,
4660
TError = DefaultError,
@@ -56,6 +70,14 @@ export interface UseSuspenseQueryOptions<
5670
>
5771
}
5872

73+
export type AnyUseInfiniteQueryOptions = UseInfiniteQueryOptions<
74+
any,
75+
any,
76+
any,
77+
any,
78+
any,
79+
any
80+
>
5981
export interface UseInfiniteQueryOptions<
6082
TQueryFnData = unknown,
6183
TError = DefaultError,
@@ -75,6 +97,8 @@ export interface UseInfiniteQueryOptions<
7597
'suspense'
7698
> {}
7799

100+
export type AnyUseSuspenseInfiniteQueryOptions =
101+
UseSuspenseInfiniteQueryOptions<any, any, any, any, any, any>
78102
export interface UseSuspenseInfiniteQueryOptions<
79103
TQueryFnData = unknown,
80104
TError = DefaultError,
@@ -147,6 +171,7 @@ export type UseSuspenseInfiniteQueryResult<
147171
'isPlaceholderData' | 'promise'
148172
>
149173

174+
export type AnyUseMutationOptions = UseMutationOptions<any, any, any, any>
150175
export interface UseMutationOptions<
151176
TData = unknown,
152177
TError = DefaultError,

0 commit comments

Comments
 (0)