Skip to content

Commit ea4497e

Browse files
ousamabenyounesclaudeTkDodo
authored
fix(query-core): stop wrapping persister generics in NoInfer (#10510)
* 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 <[email protected]> * test(react-query): wrap negative type tests in assertType Addresses CodeRabbit nitpick: vitest/expect-expect flagged the genuine-conflict test as having no assertions. Wrap both calls in assertType() so the linter sees an explicit assertion while the `@ts-expect-error` directives continue to enforce the type mismatch. Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Dominik Dorfmeister 🔮 <[email protected]>
1 parent 645d5d1 commit ea4497e

3 files changed

Lines changed: 43 additions & 5 deletions

File tree

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: 37 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,40 @@ 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+
assertType(
307+
queryOptions({
308+
queryKey: ['key'],
309+
// @ts-expect-error persister expects string, queryFn returns number
310+
queryFn: () => 42,
311+
persister,
312+
}),
313+
)
314+
315+
assertType(
316+
queryOptions({
317+
queryKey: ['key'],
318+
// @ts-expect-error persister expects string, queryFn with arg returns number
319+
queryFn: (_context) => 42,
320+
persister,
321+
}),
322+
)
323+
})
287324
})

0 commit comments

Comments
 (0)