Skip to content

Commit 175757a

Browse files
authoredDec 3, 2024··
fix(types): Fix type errors when using fully-typed inputs like QueryFilters<Data, Error>, and test all QueryClient methods to detect similar issues (#8375)
* Add test with failing types * Tidy up * Move tests to correct file * Add initial fixes (some review and testing needed) * Formatting * Ensure T params are mandatory for new overloads * Fix type issues * Unnecessary DataTag * Add typeless tests * Fix some cases * Fixing more cases * Fix some typings * Fix remaining issues * Fix linting errors * Fix one warning * Revert unnecessary change to getQueryDefaults * Remove mutation defaults todo * Rename var * Remove all additional overloads in favour of a single definition which supports all cases * Change type tests to more idomatic api
1 parent ceb4094 commit 175757a

File tree

4 files changed

+437
-47
lines changed

4 files changed

+437
-47
lines changed
 

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

+319-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
import { describe, expectTypeOf, it } from 'vitest'
22
import { QueryClient } from '../queryClient'
3-
import type { QueryState } from '../query'
4-
import type { DataTag, InfiniteData, QueryKey } from '../types'
3+
import type { MutationFilters, QueryFilters, Updater } from '../utils'
4+
import type { Mutation } from '../mutation'
5+
import type { Query, QueryState } from '../query'
6+
import type {
7+
DataTag,
8+
DefaultError,
9+
DefaultedQueryObserverOptions,
10+
EnsureQueryDataOptions,
11+
FetchInfiniteQueryOptions,
12+
InfiniteData,
13+
MutationOptions,
14+
OmitKeyof,
15+
QueryKey,
16+
QueryObserverOptions,
17+
} from '../types'
518

619
describe('getQueryData', () => {
720
it('should be typed if key is tagged', () => {
@@ -184,3 +197,307 @@ describe('defaultOptions', () => {
184197
})
185198
})
186199
})
200+
201+
describe('fully typed usage', () => {
202+
it('type-checks various methods with data & error included in the type', async () => {
203+
const queryClient = new QueryClient()
204+
205+
type TData = { foo: string }
206+
type TError = DefaultError & { bar: string }
207+
208+
//
209+
// Construct typed arguments
210+
//
211+
212+
const queryOptions: EnsureQueryDataOptions<TData, TError> = {
213+
queryKey: ['key'] as any,
214+
}
215+
const fetchInfiniteQueryOptions: FetchInfiniteQueryOptions<TData, TError> =
216+
{
217+
queryKey: ['key'] as any,
218+
pages: 5,
219+
getNextPageParam: (lastPage) => {
220+
expectTypeOf(lastPage).toEqualTypeOf<TData>()
221+
return 0
222+
},
223+
initialPageParam: 0,
224+
}
225+
const mutationOptions: MutationOptions<TData, TError> = {}
226+
227+
const queryFilters: QueryFilters<
228+
TData,
229+
TError,
230+
TData,
231+
QueryKey & DataTag<unknown, TData, TError>
232+
> = {
233+
predicate(query) {
234+
expectTypeOf(query).toEqualTypeOf<
235+
Query<
236+
TData,
237+
TError,
238+
TData,
239+
QueryKey & DataTag<unknown, TData, TError>
240+
>
241+
>()
242+
expectTypeOf(query.state.data).toEqualTypeOf<TData | undefined>()
243+
expectTypeOf(query.state.error).toEqualTypeOf<TError | null>()
244+
return false
245+
},
246+
}
247+
const queryKey = queryFilters.queryKey!
248+
249+
const mutationFilters: MutationFilters<TData, TError> = {
250+
predicate(mutation) {
251+
expectTypeOf(mutation).toEqualTypeOf<Mutation<TData, TError>>()
252+
expectTypeOf(mutation.state.data).toEqualTypeOf<TData | undefined>()
253+
expectTypeOf(mutation.state.error).toEqualTypeOf<TError | null>()
254+
return false
255+
},
256+
}
257+
const mutationKey = mutationOptions.mutationKey!
258+
259+
//
260+
// Method type tests
261+
//
262+
263+
const state = queryClient.getQueryState(queryKey)
264+
expectTypeOf(state).toEqualTypeOf<QueryState<TData, TError> | undefined>()
265+
266+
const queryData1 = queryClient.getQueryData(queryKey)
267+
expectTypeOf(queryData1).toEqualTypeOf<TData | undefined>()
268+
269+
const queryData2 = await queryClient.ensureQueryData(queryOptions)
270+
expectTypeOf(queryData2).toEqualTypeOf<TData>()
271+
272+
const queriesData = queryClient.getQueriesData(queryFilters)
273+
expectTypeOf(queriesData).toEqualTypeOf<
274+
Array<[QueryKey, TData | undefined]>
275+
>()
276+
277+
const queryData3 = queryClient.setQueryData(queryKey, { foo: '' })
278+
type SetQueryDataUpdaterArg = Parameters<
279+
typeof queryClient.setQueryData<unknown, typeof queryKey>
280+
>[1]
281+
282+
expectTypeOf<SetQueryDataUpdaterArg>().toEqualTypeOf<
283+
Updater<TData | undefined, TData | undefined>
284+
>()
285+
expectTypeOf(queryData3).toEqualTypeOf<TData | undefined>()
286+
287+
const queriesData2 = queryClient.setQueriesData(queryFilters, { foo: '' }) // TODO: types here are wrong and coming up undefined
288+
type SetQueriesDataUpdaterArg = Parameters<
289+
typeof queryClient.setQueriesData<unknown, typeof queryFilters>
290+
>[1]
291+
292+
expectTypeOf<SetQueriesDataUpdaterArg>().toEqualTypeOf<
293+
Updater<TData | undefined, TData | undefined>
294+
>()
295+
expectTypeOf(queriesData2).toEqualTypeOf<
296+
Array<[QueryKey, TData | undefined]>
297+
>()
298+
299+
const queryState = queryClient.getQueryState(queryKey)
300+
expectTypeOf(queryState).toEqualTypeOf<
301+
QueryState<TData, TError> | undefined
302+
>()
303+
304+
const fetchedQuery = await queryClient.fetchQuery(queryOptions)
305+
expectTypeOf(fetchedQuery).toEqualTypeOf<TData>()
306+
307+
queryClient.prefetchQuery(queryOptions)
308+
309+
const infiniteQuery = await queryClient.fetchInfiniteQuery(
310+
fetchInfiniteQueryOptions,
311+
)
312+
expectTypeOf(infiniteQuery).toEqualTypeOf<InfiniteData<TData, unknown>>()
313+
314+
const infiniteQueryData = await queryClient.ensureInfiniteQueryData(
315+
fetchInfiniteQueryOptions,
316+
)
317+
expectTypeOf(infiniteQueryData).toEqualTypeOf<
318+
InfiniteData<TData, unknown>
319+
>()
320+
321+
const defaultQueryOptions = queryClient.defaultQueryOptions(queryOptions)
322+
expectTypeOf(defaultQueryOptions).toEqualTypeOf<
323+
DefaultedQueryObserverOptions<TData, TError, TData, TData, QueryKey>
324+
>()
325+
326+
const mutationOptions2 = queryClient.defaultMutationOptions(mutationOptions)
327+
expectTypeOf(mutationOptions2).toEqualTypeOf<
328+
MutationOptions<TData, TError, void, unknown>
329+
>()
330+
331+
queryClient.setMutationDefaults(mutationKey, {
332+
onSettled(data, error, variables, context) {
333+
expectTypeOf(data).toEqualTypeOf<unknown>()
334+
expectTypeOf(error).toEqualTypeOf<DefaultError | null>()
335+
expectTypeOf(variables).toEqualTypeOf<void>()
336+
expectTypeOf(context).toEqualTypeOf<unknown>()
337+
},
338+
})
339+
340+
const queryDefaults = queryClient.getQueryDefaults(queryKey)
341+
expectTypeOf(queryDefaults).toEqualTypeOf<
342+
OmitKeyof<QueryObserverOptions<any, any, any, any, any>, 'queryKey'>
343+
>()
344+
345+
// Voids and Untyped returns
346+
queryClient.invalidateQueries(queryFilters)
347+
queryClient.isFetching(queryFilters)
348+
queryClient.isMutating(mutationFilters)
349+
queryClient.removeQueries(queryFilters)
350+
queryClient.resetQueries(queryFilters)
351+
queryClient.cancelQueries(queryFilters)
352+
queryClient.invalidateQueries(queryFilters)
353+
queryClient.refetchQueries(queryFilters)
354+
queryClient.prefetchInfiniteQuery(fetchInfiniteQueryOptions)
355+
queryClient.setQueryDefaults(queryKey, {} as any)
356+
queryClient.getMutationDefaults(mutationKey)
357+
})
358+
359+
it('type-checks various methods with untyped arguments', async () => {
360+
const queryClient = new QueryClient()
361+
362+
//
363+
// Construct typed arguments
364+
//
365+
366+
const queryOptions: EnsureQueryDataOptions = {
367+
queryKey: ['key'] as any,
368+
}
369+
const fetchInfiniteQueryOptions: FetchInfiniteQueryOptions = {
370+
queryKey: ['key'] as any,
371+
pages: 5,
372+
getNextPageParam: (lastPage) => {
373+
expectTypeOf(lastPage).toEqualTypeOf<unknown>()
374+
return 0
375+
},
376+
initialPageParam: 0,
377+
}
378+
const mutationOptions: MutationOptions = {}
379+
380+
const queryFilters: QueryFilters = {
381+
predicate(query) {
382+
expectTypeOf(query).toEqualTypeOf<Query<unknown, DefaultError>>()
383+
expectTypeOf(query.state.data).toEqualTypeOf<unknown>()
384+
expectTypeOf(query.state.error).toEqualTypeOf<DefaultError | null>()
385+
return false
386+
},
387+
}
388+
const queryKey = queryFilters.queryKey!
389+
390+
const mutationFilters: MutationFilters = {
391+
predicate(mutation) {
392+
expectTypeOf(mutation).toEqualTypeOf<Mutation>()
393+
expectTypeOf(mutation.state.data).toEqualTypeOf<unknown>()
394+
expectTypeOf(mutation.state.error).toEqualTypeOf<DefaultError | null>()
395+
return false
396+
},
397+
}
398+
const mutationKey = mutationOptions.mutationKey!
399+
400+
//
401+
// Method type tests
402+
//
403+
404+
const state = queryClient.getQueryState(queryKey)
405+
expectTypeOf(state).toEqualTypeOf<
406+
QueryState<unknown, DefaultError> | undefined
407+
>()
408+
409+
const queryData1 = queryClient.getQueryData(queryKey)
410+
expectTypeOf(queryData1).toEqualTypeOf<unknown>()
411+
412+
const queryData2 = await queryClient.ensureQueryData(queryOptions)
413+
expectTypeOf(queryData2).toEqualTypeOf<unknown>()
414+
415+
const queriesData = queryClient.getQueriesData(queryFilters)
416+
expectTypeOf(queriesData).toEqualTypeOf<Array<[QueryKey, unknown]>>()
417+
418+
const queryData3 = queryClient.setQueryData(queryKey, { foo: '' })
419+
type SetQueryDataUpdaterArg = Parameters<
420+
typeof queryClient.setQueryData<unknown, typeof queryKey>
421+
>[1]
422+
423+
expectTypeOf<SetQueryDataUpdaterArg>().toEqualTypeOf<
424+
Updater<unknown, unknown>
425+
>()
426+
expectTypeOf(queryData3).toEqualTypeOf<unknown>()
427+
428+
const queriesData2 = queryClient.setQueriesData(queryFilters, { foo: '' }) // TODO: types here are wrong and coming up undefined
429+
type SetQueriesDataUpdaterArg = Parameters<
430+
typeof queryClient.setQueriesData<unknown, typeof queryFilters>
431+
>[1]
432+
433+
expectTypeOf<SetQueriesDataUpdaterArg>().toEqualTypeOf<
434+
Updater<unknown, unknown>
435+
>()
436+
expectTypeOf(queriesData2).toEqualTypeOf<Array<[QueryKey, unknown]>>()
437+
438+
const queryState = queryClient.getQueryState(queryKey)
439+
expectTypeOf(queryState).toEqualTypeOf<
440+
QueryState<unknown, DefaultError> | undefined
441+
>()
442+
443+
const fetchedQuery = await queryClient.fetchQuery(queryOptions)
444+
expectTypeOf(fetchedQuery).toEqualTypeOf<unknown>()
445+
446+
queryClient.prefetchQuery(queryOptions)
447+
448+
const infiniteQuery = await queryClient.fetchInfiniteQuery(
449+
fetchInfiniteQueryOptions,
450+
)
451+
expectTypeOf(infiniteQuery).toEqualTypeOf<InfiniteData<unknown, unknown>>()
452+
453+
const infiniteQueryData = await queryClient.ensureInfiniteQueryData(
454+
fetchInfiniteQueryOptions,
455+
)
456+
expectTypeOf(infiniteQueryData).toEqualTypeOf<
457+
InfiniteData<unknown, unknown>
458+
>()
459+
460+
const defaultQueryOptions = queryClient.defaultQueryOptions(queryOptions)
461+
expectTypeOf(defaultQueryOptions).toEqualTypeOf<
462+
DefaultedQueryObserverOptions<
463+
unknown,
464+
DefaultError,
465+
unknown,
466+
unknown,
467+
QueryKey
468+
>
469+
>()
470+
471+
const mutationOptions2 = queryClient.defaultMutationOptions(mutationOptions)
472+
expectTypeOf(mutationOptions2).toEqualTypeOf<
473+
MutationOptions<unknown, DefaultError, void, unknown>
474+
>()
475+
476+
queryClient.setMutationDefaults(mutationKey, {
477+
onSettled(data, error, variables, context) {
478+
expectTypeOf(data).toEqualTypeOf<unknown>()
479+
expectTypeOf(error).toEqualTypeOf<DefaultError | null>()
480+
expectTypeOf(variables).toEqualTypeOf<void>()
481+
expectTypeOf(context).toEqualTypeOf<unknown>()
482+
},
483+
})
484+
485+
const queryDefaults = queryClient.getQueryDefaults(queryKey)
486+
expectTypeOf(queryDefaults).toEqualTypeOf<
487+
OmitKeyof<QueryObserverOptions<any, any, any, any, any>, 'queryKey'>
488+
>()
489+
490+
// Voids and Untyped returns
491+
queryClient.invalidateQueries(queryFilters)
492+
queryClient.isFetching(queryFilters)
493+
queryClient.isMutating(mutationFilters)
494+
queryClient.removeQueries(queryFilters)
495+
queryClient.resetQueries(queryFilters)
496+
queryClient.cancelQueries(queryFilters)
497+
queryClient.invalidateQueries(queryFilters)
498+
queryClient.refetchQueries(queryFilters)
499+
queryClient.prefetchInfiniteQuery(fetchInfiniteQueryOptions)
500+
queryClient.setQueryDefaults(queryKey, {} as any)
501+
queryClient.getMutationDefaults(mutationKey)
502+
})
503+
})

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

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
import { describe, expectTypeOf, it } from 'vitest'
22
import { QueryClient } from '../queryClient'
33
import type { QueryFilters } from '../utils'
4-
import type { DataTag } from '../types'
4+
import type { DataTag, QueryKey } from '../types'
55

66
describe('QueryFilters', () => {
77
it('should be typed if generics are passed', () => {
88
type TData = { a: number; b: string }
99

10-
const a: QueryFilters<TData> = {
10+
const filters: QueryFilters<
11+
TData,
12+
Error,
13+
TData,
14+
QueryKey & DataTag<unknown, TData>
15+
> = {
1116
predicate(query) {
1217
expectTypeOf(query.setData({ a: 1, b: '1' })).toEqualTypeOf<TData>()
1318
return true
@@ -17,18 +22,23 @@ describe('QueryFilters', () => {
1722

1823
const queryClient = new QueryClient()
1924

20-
const data = queryClient.getQueryData(a.queryKey!)
25+
const data = queryClient.getQueryData(filters.queryKey!)
2126
expectTypeOf(data).toEqualTypeOf<TData | undefined>()
2227

23-
const error = queryClient.getQueryState(a.queryKey!)?.error
28+
const error = queryClient.getQueryState(filters.queryKey!)?.error
2429
expectTypeOf(error).toEqualTypeOf<Error | null | undefined>()
2530
})
2631

2732
it('should be typed if generics are passed including an error type', () => {
2833
type TData = { a: number; b: string }
2934
type TError = Error & { message: string }
3035

31-
const a: QueryFilters<TData, TError> = {
36+
const filters: QueryFilters<
37+
TData,
38+
TError,
39+
TData,
40+
QueryKey & DataTag<unknown, TData, TError>
41+
> = {
3242
predicate(query) {
3343
expectTypeOf(query.setData({ a: 1, b: '1' })).toEqualTypeOf<TData>()
3444
return true
@@ -38,10 +48,10 @@ describe('QueryFilters', () => {
3848

3949
const queryClient = new QueryClient()
4050

41-
const data = queryClient.getQueryData(a.queryKey!)
51+
const data = queryClient.getQueryData(filters.queryKey!)
4252
expectTypeOf(data).toEqualTypeOf<TData | undefined>()
4353

44-
const error = queryClient.getQueryState(a.queryKey!)?.error
54+
const error = queryClient.getQueryState(filters.queryKey!)?.error
4555
expectTypeOf(error).toEqualTypeOf<TError | null | undefined>()
4656
})
4757

‎packages/query-core/src/queryClient.ts

+91-32
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,16 @@ export class QueryClient {
106106
this.#unsubscribeOnline = undefined
107107
}
108108

109-
isFetching(filters?: QueryFilters): number {
109+
isFetching<
110+
TQueryFilters extends QueryFilters<any, any, any, any> = QueryFilters,
111+
>(filters?: TQueryFilters): number {
110112
return this.#queryCache.findAll({ ...filters, fetchStatus: 'fetching' })
111113
.length
112114
}
113115

114-
isMutating(filters?: MutationFilters): number {
116+
isMutating<
117+
TMutationFilters extends MutationFilters<any, any> = MutationFilters,
118+
>(filters?: TMutationFilters): number {
115119
return this.#mutationCache.findAll({ ...filters, status: 'pending' }).length
116120
}
117121

@@ -125,10 +129,12 @@ export class QueryClient {
125129
>
126130
? TaggedValue
127131
: TQueryFnData,
128-
>(queryKey: TTaggedQueryKey): TInferredQueryFnData | undefined
129-
getQueryData(queryKey: QueryKey) {
132+
>(queryKey: TTaggedQueryKey): TInferredQueryFnData | undefined {
130133
const options = this.defaultQueryOptions({ queryKey })
131-
return this.#queryCache.get(options.queryHash)?.state.data
134+
135+
return this.#queryCache.get(options.queryHash)?.state.data as
136+
| TInferredQueryFnData
137+
| undefined
132138
}
133139

134140
ensureQueryData<
@@ -141,8 +147,9 @@ export class QueryClient {
141147
): Promise<TData> {
142148
const cachedData = this.getQueryData<TData>(options.queryKey)
143149

144-
if (cachedData === undefined) return this.fetchQuery(options)
145-
else {
150+
if (cachedData === undefined) {
151+
return this.fetchQuery(options)
152+
} else {
146153
const defaultedOptions = this.defaultQueryOptions(options)
147154
const query = this.#queryCache.build(this, defaultedOptions)
148155

@@ -157,11 +164,27 @@ export class QueryClient {
157164
}
158165
}
159166

160-
getQueriesData<TQueryFnData = unknown>(
161-
filters: QueryFilters,
162-
): Array<[QueryKey, TQueryFnData | undefined]> {
167+
getQueriesData<
168+
TQueryFnData = unknown,
169+
TQueryFilters extends QueryFilters<
170+
any,
171+
any,
172+
any,
173+
any
174+
> = QueryFilters<TQueryFnData>,
175+
TInferredQueryFnData = TQueryFilters extends QueryFilters<
176+
infer TData,
177+
any,
178+
any,
179+
any
180+
>
181+
? TData
182+
: TQueryFnData,
183+
>(
184+
filters: TQueryFilters,
185+
): Array<[QueryKey, TInferredQueryFnData | undefined]> {
163186
return this.#queryCache.findAll(filters).map(({ queryKey, state }) => {
164-
const data = state.data as TQueryFnData | undefined
187+
const data = state.data as TInferredQueryFnData | undefined
165188
return [queryKey, data]
166189
})
167190
}
@@ -207,17 +230,36 @@ export class QueryClient {
207230
.setData(data, { ...options, manual: true })
208231
}
209232

210-
setQueriesData<TQueryFnData>(
211-
filters: QueryFilters,
212-
updater: Updater<TQueryFnData | undefined, TQueryFnData | undefined>,
233+
setQueriesData<
234+
TQueryFnData,
235+
TQueryFilters extends QueryFilters<
236+
any,
237+
any,
238+
any,
239+
any
240+
> = QueryFilters<TQueryFnData>,
241+
TInferredQueryFnData = TQueryFilters extends QueryFilters<
242+
infer TData,
243+
any,
244+
any,
245+
any
246+
>
247+
? TData
248+
: TQueryFnData,
249+
>(
250+
filters: TQueryFilters,
251+
updater: Updater<
252+
NoInfer<TInferredQueryFnData> | undefined,
253+
NoInfer<TInferredQueryFnData> | undefined
254+
>,
213255
options?: SetDataOptions,
214-
): Array<[QueryKey, TQueryFnData | undefined]> {
256+
): Array<[QueryKey, TInferredQueryFnData | undefined]> {
215257
return notifyManager.batch(() =>
216258
this.#queryCache
217259
.findAll(filters)
218260
.map(({ queryKey }) => [
219261
queryKey,
220-
this.setQueryData<TQueryFnData>(queryKey, updater, options),
262+
this.setQueryData<TInferredQueryFnData>(queryKey, updater, options),
221263
]),
222264
)
223265
}
@@ -251,7 +293,9 @@ export class QueryClient {
251293
)?.state
252294
}
253295

254-
removeQueries(filters?: QueryFilters): void {
296+
removeQueries<
297+
TQueryFilters extends QueryFilters<any, any, any, any> = QueryFilters,
298+
>(filters?: TQueryFilters): void {
255299
const queryCache = this.#queryCache
256300
notifyManager.batch(() => {
257301
queryCache.findAll(filters).forEach((query) => {
@@ -260,7 +304,9 @@ export class QueryClient {
260304
})
261305
}
262306

263-
resetQueries(filters?: QueryFilters, options?: ResetOptions): Promise<void> {
307+
resetQueries<
308+
TQueryFilters extends QueryFilters<any, any, any, any> = QueryFilters,
309+
>(filters?: TQueryFilters, options?: ResetOptions): Promise<void> {
264310
const queryCache = this.#queryCache
265311

266312
const refetchFilters: RefetchQueryFilters = {
@@ -276,10 +322,9 @@ export class QueryClient {
276322
})
277323
}
278324

279-
cancelQueries(
280-
filters: QueryFilters = {},
281-
cancelOptions: CancelOptions = {},
282-
): Promise<void> {
325+
cancelQueries<
326+
TQueryFilters extends QueryFilters<any, any, any, any> = QueryFilters,
327+
>(filters?: TQueryFilters, cancelOptions: CancelOptions = {}): Promise<void> {
283328
const defaultedCancelOptions = { revert: true, ...cancelOptions }
284329

285330
const promises = notifyManager.batch(() =>
@@ -291,33 +336,47 @@ export class QueryClient {
291336
return Promise.all(promises).then(noop).catch(noop)
292337
}
293338

294-
invalidateQueries(
295-
filters: InvalidateQueryFilters = {},
339+
invalidateQueries<
340+
TInvalidateQueryFilters extends InvalidateQueryFilters<
341+
any,
342+
any,
343+
any,
344+
any
345+
> = InvalidateQueryFilters,
346+
>(
347+
filters?: TInvalidateQueryFilters,
296348
options: InvalidateOptions = {},
297349
): Promise<void> {
298350
return notifyManager.batch(() => {
299351
this.#queryCache.findAll(filters).forEach((query) => {
300352
query.invalidate()
301353
})
302354

303-
if (filters.refetchType === 'none') {
355+
if (filters?.refetchType === 'none') {
304356
return Promise.resolve()
305357
}
306358
const refetchFilters: RefetchQueryFilters = {
307359
...filters,
308-
type: filters.refetchType ?? filters.type ?? 'active',
360+
type: filters?.refetchType ?? filters?.type ?? 'active',
309361
}
310362
return this.refetchQueries(refetchFilters, options)
311363
})
312364
}
313365

314-
refetchQueries(
315-
filters: RefetchQueryFilters = {},
316-
options?: RefetchOptions,
366+
refetchQueries<
367+
TRefetchQueryFilters extends RefetchQueryFilters<
368+
any,
369+
any,
370+
any,
371+
any
372+
> = RefetchQueryFilters,
373+
>(
374+
filters?: TRefetchQueryFilters,
375+
options: RefetchOptions = {},
317376
): Promise<void> {
318377
const fetchOptions = {
319378
...options,
320-
cancelRefetch: options?.cancelRefetch ?? true,
379+
cancelRefetch: options.cancelRefetch ?? true,
321380
}
322381
const promises = notifyManager.batch(() =>
323382
this.#queryCache
@@ -494,14 +553,14 @@ export class QueryClient {
494553
): OmitKeyof<QueryObserverOptions<any, any, any, any, any>, 'queryKey'> {
495554
const defaults = [...this.#queryDefaults.values()]
496555

497-
let result: OmitKeyof<
556+
const result: OmitKeyof<
498557
QueryObserverOptions<any, any, any, any, any>,
499558
'queryKey'
500559
> = {}
501560

502561
defaults.forEach((queryDefault) => {
503562
if (partialMatchKey(queryKey, queryDefault.queryKey)) {
504-
result = { ...result, ...queryDefault.defaultOptions }
563+
Object.assign(result, queryDefault.defaultOptions)
505564
}
506565
})
507566
return result

‎packages/query-core/src/utils.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type {
2-
DataTag,
32
DefaultError,
43
Enabled,
54
FetchStatus,
@@ -36,9 +35,7 @@ export interface QueryFilters<
3635
/**
3736
* Include queries matching this query key
3837
*/
39-
queryKey?: unknown extends TQueryFnData
40-
? QueryKey
41-
: QueryKey & DataTag<unknown, TQueryFnData, TError>
38+
queryKey?: TQueryKey
4239
/**
4340
* Include or exclude stale queries
4441
*/
@@ -49,15 +46,22 @@ export interface QueryFilters<
4946
fetchStatus?: FetchStatus
5047
}
5148

52-
export interface MutationFilters {
49+
export interface MutationFilters<
50+
TData = unknown,
51+
TError = DefaultError,
52+
TVariables = unknown,
53+
TContext = unknown,
54+
> {
5355
/**
5456
* Match mutation key exactly
5557
*/
5658
exact?: boolean
5759
/**
5860
* Include mutations matching this predicate function
5961
*/
60-
predicate?: (mutation: Mutation<any, any, any>) => boolean
62+
predicate?: (
63+
mutation: Mutation<TData, TError, TVariables, TContext>,
64+
) => boolean
6165
/**
6266
* Include mutations matching this mutation key
6367
*/

0 commit comments

Comments
 (0)
Please sign in to comment.