fix(query-core): stop wrapping persister generics in NoInfer#10510
fix(query-core): stop wrapping persister generics in NoInfer#10510TkDodo merged 4 commits intoTanStack:mainfrom
Conversation
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 TanStack#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]>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthroughThis PR removes Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/react-query/src/__tests__/queryOptions.test-d.tsx (1)
303-319: Minor: silencevitest/expect-expectfor this type-only negative test.ESLint flags this test as having no assertions because
@ts-expect-erroris the implicit assertion. Either disable the rule locally or wrap the calls inassertType(...)to satisfy the linter.Proposed fix
- it('should still error when persister and queryFn return types genuinely conflict', () => { + // eslint-disable-next-line vitest/expect-expect + it('should still error when persister and queryFn return types genuinely conflict', () => { const persister = undefined as unknown as QueryPersister<string, any>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/react-query/src/__tests__/queryOptions.test-d.tsx` around lines 303 - 319, This test is a type-only negative test using `@ts-expect-error` but triggers the vitest/expect-expect lint rule; either disable the rule locally for this block or add a no-op type assertion to make ESLint happy. Modify the test in packages/react-query/src/__tests__/queryOptions.test-d.tsx around the two queryOptions(...) calls: either add an inline ESLint disable comment for "vitest/expect-expect" scoped to the test, or wrap each call with a type-level helper such as assertType<unknown>(queryOptions(...)) (or another existing assertType utility) so the linter sees an assertion while preserving the `@ts-expect-error` checks on queryFn vs persister.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/react-query/src/__tests__/queryOptions.test-d.tsx`:
- Around line 303-319: This test is a type-only negative test using
`@ts-expect-error` but triggers the vitest/expect-expect lint rule; either disable
the rule locally for this block or add a no-op type assertion to make ESLint
happy. Modify the test in
packages/react-query/src/__tests__/queryOptions.test-d.tsx around the two
queryOptions(...) calls: either add an inline ESLint disable comment for
"vitest/expect-expect" scoped to the test, or wrap each call with a type-level
helper such as assertType<unknown>(queryOptions(...)) (or another existing
assertType utility) so the linter sees an assertion while preserving the
`@ts-expect-error` checks on queryFn vs persister.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 878349b8-d2be-4c9a-816a-c2d3de88ede1
📒 Files selected for processing (3)
.changeset/fix-persister-infer-when-queryfn-has-parameter.mdpackages/query-core/src/types.tspackages/react-query/src/__tests__/queryOptions.test-d.tsx
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]>
|
Addressed the |
|
View your CI Pipeline Execution ↗ for commit 85317f2
☁️ Nx Cloud last updated this comment at |
More templates
@tanstack/angular-query-experimental
@tanstack/eslint-plugin-query
@tanstack/preact-query
@tanstack/preact-query-devtools
@tanstack/preact-query-persist-client
@tanstack/query-async-storage-persister
@tanstack/query-broadcast-client-experimental
@tanstack/query-core
@tanstack/query-devtools
@tanstack/query-persist-client-core
@tanstack/query-sync-storage-persister
@tanstack/react-query
@tanstack/react-query-devtools
@tanstack/react-query-next-experimental
@tanstack/react-query-persist-client
@tanstack/solid-query
@tanstack/solid-query-devtools
@tanstack/solid-query-persist-client
@tanstack/svelte-query
@tanstack/svelte-query-devtools
@tanstack/svelte-query-persist-client
@tanstack/vue-query
@tanstack/vue-query-devtools
commit: |
persister slot drags TQueryKey into inference, breaking Register.queryKey + DataTag consumers
#10600
Follow-up to #10510. That PR removed NoInfer from all three persister generics to fix TQueryFnData inference when the companion queryFn declares a parameter (#7842). Keeping NoInfer on TQueryKey preserves that fix while preventing the persister slot from widening TQueryKey inference. Without NoInfer on TQueryKey, the persister slot contributes to TQueryKey inference. When Register.queryKey is augmented to a narrowed constraint, TQueryKey widens to that constraint instead of the literal passed to queryKey. Wrappers that brand their return with DataTag<TQueryKey, ...> then produce a brand on the wider type, which a plain literal tuple can no longer satisfy in contravariant positions (vi.mocked(...).mockReturnValue, typed variable assignments, etc.). TQueryFnData still participates in inference, so #10510's positive and negative type tests continue to pass. Co-authored-by: Wonsuk Choi <[email protected]>
Summary
Fixes #7842.
QueryOptions.persisterwas typed asQueryPersister<NoInfer<TQueryFnData>, NoInfer<TQueryKey>, NoInfer<TPageParam>>, which prevented the persister from contributing toTQueryFnDatainference. When the companionqueryFndeclared a parameter (e.g.(_context) => 'test'), TypeScript failed to inferTQueryFnDatafrom its return and defaulted tounknown, producing a spurious overload mismatch against a concretely-typed persister.Removing the
NoInferwrappers letspersisterparticipate in inference.queryFnstill drives inference when the types agree, and genuine conflicts betweenpersisterandqueryFnstill surface as errors (covered by a new negative type test inqueryOptions.test-d.tsx).Repro
Verification
packages/query-coretype tests: pass across TS 5.4, 5.8, 6.0 current (tsc --build tsconfig.legacy.json)packages/react-querytype tests: pass (new positive + negative cases inqueryOptions.test-d.tsx)packages/vue-query,packages/solid-query,packages/preact-querytype tests: passqueryFn: () => 42withpersister: QueryPersister<string>) still produce the expected overload mismatch — verified by the new@ts-expect-errorcases.Changeset
@tanstack/query-core: patch — type-only change, no runtime behaviour affected.🤖 Generated with Ora Studio
Summary by CodeRabbit
Bug Fixes
Tests