From 1546819aec582076bf373759f6f818f2741ab51a Mon Sep 17 00:00:00 2001 From: Ousama Ben Younes Date: Thu, 16 Apr 2026 22:36:44 +0000 Subject: [PATCH 1/2] fix(query-core): stop wrapping persister generics in NoInfer The `persister` field on QueryOptions was typed as `QueryPersister, NoInfer, NoInfer>` 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 --- ...sister-infer-when-queryfn-has-parameter.md | 5 +++ packages/query-core/src/types.ts | 6 +--- .../src/__tests__/queryOptions.test-d.tsx | 33 +++++++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 .changeset/fix-persister-infer-when-queryfn-has-parameter.md diff --git a/.changeset/fix-persister-infer-when-queryfn-has-parameter.md b/.changeset/fix-persister-infer-when-queryfn-has-parameter.md new file mode 100644 index 00000000000..ef3ca442a38 --- /dev/null +++ b/.changeset/fix-persister-infer-when-queryfn-has-parameter.md @@ -0,0 +1,5 @@ +--- +'@tanstack/query-core': patch +--- + +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). diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index 4f3f4caed20..b3904bdba4a 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -246,11 +246,7 @@ export interface QueryOptions< */ gcTime?: number queryFn?: QueryFunction | SkipToken - persister?: QueryPersister< - NoInfer, - NoInfer, - NoInfer - > + persister?: QueryPersister queryHash?: string queryKey?: TQueryKey queryKeyHashFn?: QueryKeyHashFunction diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index dcfaeab6589..3593fd41a9b 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -15,6 +15,7 @@ import type { DataTag, InitialDataFunction, QueryObserverResult, + QueryPersister, } from '@tanstack/query-core' describe('queryOptions', () => { @@ -284,4 +285,36 @@ describe('queryOptions', () => { DataTag >() }) + + it('should infer TQueryFnData from persister paired with a queryFn declaring a parameter (#7842)', () => { + const persister = undefined as unknown as QueryPersister + + const options = queryOptions({ + queryKey: ['key'], + queryFn: (_context) => 'hello', + persister, + }) + + expectTypeOf(options.queryFn!).returns.toEqualTypeOf< + string | Promise + >() + }) + + it('should still error when persister and queryFn return types genuinely conflict', () => { + const persister = undefined as unknown as QueryPersister + + queryOptions({ + queryKey: ['key'], + // @ts-expect-error persister expects string, queryFn returns number + queryFn: () => 42, + persister, + }) + + queryOptions({ + queryKey: ['key'], + // @ts-expect-error persister expects string, queryFn with arg returns number + queryFn: (_context) => 42, + persister, + }) + }) }) From cbc0246d35fdcf137359e47417c9bf4ac6831c01 Mon Sep 17 00:00:00 2001 From: Ousama Ben Younes Date: Thu, 16 Apr 2026 22:59:20 +0000 Subject: [PATCH 2/2] 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 --- .../src/__tests__/queryOptions.test-d.tsx | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index 3593fd41a9b..14f92a8da3e 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -303,18 +303,22 @@ describe('queryOptions', () => { it('should still error when persister and queryFn return types genuinely conflict', () => { const persister = undefined as unknown as QueryPersister - queryOptions({ - queryKey: ['key'], - // @ts-expect-error persister expects string, queryFn returns number - queryFn: () => 42, - persister, - }) + assertType( + queryOptions({ + queryKey: ['key'], + // @ts-expect-error persister expects string, queryFn returns number + queryFn: () => 42, + persister, + }), + ) - queryOptions({ - queryKey: ['key'], - // @ts-expect-error persister expects string, queryFn with arg returns number - queryFn: (_context) => 42, - persister, - }) + assertType( + queryOptions({ + queryKey: ['key'], + // @ts-expect-error persister expects string, queryFn with arg returns number + queryFn: (_context) => 42, + persister, + }), + ) }) })