Skip to content

Commit 1546819

Browse files
fix(query-core): stop wrapping persister generics in NoInfer
The `persister` field on QueryOptions was typed as `QueryPersister<NoInfer<TQueryFnData>, NoInfer<TQueryKey>, NoInfer<TPageParam>>` so persister could not contribute to TQueryFnData inference. When the companion queryFn declared a parameter (e.g. `(_context) => 'test'`), TypeScript failed to infer TQueryFnData from its return and defaulted to `unknown`, causing a spurious overload mismatch against a concretely-typed persister (fixes #7842). Removing the NoInfer wrappers lets persister participate in inference. Genuine type conflicts between persister and queryFn still surface as errors (covered by a new negative type test in queryOptions.test-d.tsx). Co-Authored-By: Claude <noreply@anthropic.com>
1 parent dbee9eb commit 1546819

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/query-core': patch
3+
---
4+
5+
fix(query-core): allow `persister` to contribute to `TQueryFnData` inference so a `queryFn` that declares a parameter no longer produces a spurious overload mismatch against a typed persister (#7842).

packages/query-core/src/types.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,7 @@ export interface QueryOptions<
246246
*/
247247
gcTime?: number
248248
queryFn?: QueryFunction<TQueryFnData, TQueryKey, TPageParam> | SkipToken
249-
persister?: QueryPersister<
250-
NoInfer<TQueryFnData>,
251-
NoInfer<TQueryKey>,
252-
NoInfer<TPageParam>
253-
>
249+
persister?: QueryPersister<TQueryFnData, TQueryKey, TPageParam>
254250
queryHash?: string
255251
queryKey?: TQueryKey
256252
queryKeyHashFn?: QueryKeyHashFunction<TQueryKey>

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {
1515
DataTag,
1616
InitialDataFunction,
1717
QueryObserverResult,
18+
QueryPersister,
1819
} from '@tanstack/query-core'
1920

2021
describe('queryOptions', () => {
@@ -284,4 +285,36 @@ describe('queryOptions', () => {
284285
DataTag<MyQueryKey, number, Error & { myMessage: string }>
285286
>()
286287
})
288+
289+
it('should infer TQueryFnData from persister paired with a queryFn declaring a parameter (#7842)', () => {
290+
const persister = undefined as unknown as QueryPersister<string, any>
291+
292+
const options = queryOptions({
293+
queryKey: ['key'],
294+
queryFn: (_context) => 'hello',
295+
persister,
296+
})
297+
298+
expectTypeOf(options.queryFn!).returns.toEqualTypeOf<
299+
string | Promise<string>
300+
>()
301+
})
302+
303+
it('should still error when persister and queryFn return types genuinely conflict', () => {
304+
const persister = undefined as unknown as QueryPersister<string, any>
305+
306+
queryOptions({
307+
queryKey: ['key'],
308+
// @ts-expect-error persister expects string, queryFn returns number
309+
queryFn: () => 42,
310+
persister,
311+
})
312+
313+
queryOptions({
314+
queryKey: ['key'],
315+
// @ts-expect-error persister expects string, queryFn with arg returns number
316+
queryFn: (_context) => 42,
317+
persister,
318+
})
319+
})
287320
})

0 commit comments

Comments
 (0)