Skip to content

Conversation

@DogPawHat
Copy link
Contributor

@DogPawHat DogPawHat commented Nov 1, 2025

🎯 Changes

Implements #9135

  • renames fetchQuery and fetchInfiniteQuery to query and infiniteQuery
  • make new fetch* aliases for the renamed methods
  • delegates the prefetch* methods with query instead of fetchQuery
  • delegates ensureQueryData methods to query with staletime: 'static'
  • updates tests for QueryClient (straight copy of the fetch tests)
  • added new methods to vue-query QueryClient subclass.

TODO when this is merged (I have stacked branchs for these)

  • add new docs
  • refactor all the other tests to use the new methods (can be split up by package)
  • add deprecation tags to old methods

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • New Features

    • Added new imperative query methods (including infinite queries), exported InfiniteQueryExecuteOptions, and a public noop helper.
    • select is supported on the new imperative query paths; fetchQuery/fetchInfiniteQuery continue to ignore select.
  • Chores

    • Package bumps and renamed imperative surface with compatibility wrappers preserved.
  • Tests

    • Expanded coverage for staleTime, infinite paging, prefetching, select interactions, edge cases and typings.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Nov 1, 2025

🦋 Changeset detected

Latest commit: bf15113

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 19 packages
Name Type
@tanstack/react-query Minor
@tanstack/query-core Minor
@tanstack/vue-query Minor
@tanstack/react-query-devtools Major
@tanstack/react-query-next-experimental Major
@tanstack/react-query-persist-client Major
@tanstack/angular-query-experimental Patch
@tanstack/query-async-storage-persister Patch
@tanstack/query-broadcast-client-experimental Patch
@tanstack/query-persist-client-core Patch
@tanstack/query-sync-storage-persister Patch
@tanstack/solid-query Patch
@tanstack/svelte-query Patch
@tanstack/vue-query-devtools Major
@tanstack/angular-query-persist-client Patch
@tanstack/solid-query-persist-client Patch
@tanstack/svelte-query-persist-client Patch
@tanstack/solid-query-devtools Patch
@tanstack/svelte-query-devtools Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 1, 2025

Walkthrough

Adds new imperative execute methods query and infiniteQuery, exports QueryExecuteOptions / InfiniteQueryExecuteOptions, renames FetchInfiniteQueryPagesInfiniteQueryPages, updates typings/tests for select and staleTime, and wires infinite flows through the new execute surface.

Changes

Cohort / File(s) Change Summary
Core Client Implementation
packages/query-core/src/queryClient.ts
Added query and infiniteQuery methods with overloads using QueryExecuteOptions / InfiniteQueryExecuteOptions; infinite flow routed via the new execute surface; updated fetchInfiniteQuery overloads/wrappers.
Public Types & Typings
packages/query-core/src/types.ts
Added QueryExecuteOptions, exported InfiniteQueryExecuteOptions, introduced/renamed InfiniteQueryPages (was FetchInfiniteQueryPages), and updated related FetchInfiniteQueryOptions and type references.
Core Tests & Public Helpers
packages/query-core/src/__tests__/queryClient.test.tsx, packages/query-core/src/__tests__/queryClient.test-d.tsx
Tests updated/expanded for static staleTime, infinite-query scenarios, select behavior, and fully-typed usage; type tests updated to reference InfiniteQueryExecuteOptions; added test import usage of exported noop.
React Type Tests
packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx, packages/react-query/src/__tests__/queryOptions.test-d.tsx
Added/updated type assertions validating select behavior across useInfiniteQuery, useSuspenseInfiniteQuery, infiniteQuery, and fetchInfiniteQuery/fetchQuery (select ignored for fetch variants).
Vue Integration
packages/vue-query/src/queryClient.ts
Added query and infiniteQuery overloads (plain and MaybeRefDeep variants) delegating to super with cloneDeepUnref; type signatures updated to match core execute-option types.
Changeset
.changeset/famous-owls-battle.md
Package bumps for @tanstack/react-query, @tanstack/query-core, @tanstack/vue-query; note about renamed imperative methods.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Caller as Caller
    participant QClient as QueryClient
    participant Executor as Execute Core
    participant Cache as Cache / Network
    participant Selector as Select (optional)

    Caller->>QClient: query(opts) / infiniteQuery(opts)
    QClient->>Executor: delegate(QueryExecuteOptions / InfiniteQueryExecuteOptions)
    Executor->>Cache: fetch raw TQueryData or pages
    Cache-->>Executor: raw TQueryData or pages
    alt select provided
        Executor->>Selector: apply select(raw data/pages)
        Selector-->>Executor: transformed TData or pages
    end
    Executor-->>QClient: Promise<TData or InfiniteData>
    QClient-->>Caller: resolved data
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Pay special attention to:
    • packages/query-core/src/types.ts — new generics and renamed pagination types.
    • packages/query-core/src/queryClient.ts — overloads, routing, staleTime/select semantics.
    • packages/query-core/src/__tests__/queryClient.test.tsx and .test-d.tsx — expanded runtime and type coverage.
    • Cross-package typings in packages/vue-query and react type tests.

Suggested reviewers

  • TkDodo

Poem

🐰 I tunneled through types and hopped in delight,
added two paths that now run just right.
Pages bound forward, selects take their cue,
noop waved softly — tests nodded too.
🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'init query rename and delegation' is vague and generic, using non-descriptive terms that don't clearly convey the main changes (renaming fetchQuery/fetchInfiniteQuery to query/infiniteQuery or the delegation strategy). Use a more specific title like 'Rename fetchQuery/fetchInfiniteQuery to query/infiniteQuery' or 'Implement simplified imperative query methods' to clearly communicate the primary change.
✅ Passed checks (2 passed)
Check name Status Explanation
Description check ✅ Passed The PR description is comprehensive and follows the template structure with filled-out Changes and Checklist sections, clearly documenting the implementation and confirming testing and changeset generation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Nov 1, 2025

View your CI Pipeline Execution ↗ for commit bf15113

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 1m 45s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 2s View ↗

☁️ Nx Cloud last updated this comment at 2025-11-27 21:02:53 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 1, 2025

More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@9835

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@9835

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@9835

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@9835

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@9835

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@9835

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@9835

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@9835

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@9835

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@9835

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@9835

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@9835

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@9835

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@9835

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@9835

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@9835

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@9835

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@9835

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@9835

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@9835

commit: bf15113

@TkDodo
Copy link
Collaborator

TkDodo commented Nov 1, 2025

renames fetchQuery and fetchInfiniteQuery to query and infiniteQuery

sorry the idea was not to rename those, but to add new methods and deprecate the old ones. Otherwise, this would be a breaking change.

@codecov
Copy link

codecov bot commented Nov 1, 2025

Codecov Report

❌ Patch coverage is 75.00000% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 59.97%. Comparing base (aba3260) to head (bf15113).

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #9835       +/-   ##
===========================================
+ Coverage   45.89%   59.97%   +14.07%     
===========================================
  Files         200      129       -71     
  Lines        8437     5671     -2766     
  Branches     1940     1544      -396     
===========================================
- Hits         3872     3401      -471     
+ Misses       4116     1964     -2152     
+ Partials      449      306      -143     
Components Coverage Δ
@tanstack/angular-query-experimental 93.85% <ø> (ø)
@tanstack/eslint-plugin-query ∅ <ø> (∅)
@tanstack/query-async-storage-persister 43.85% <ø> (ø)
@tanstack/query-broadcast-client-experimental 24.39% <ø> (ø)
@tanstack/query-codemods ∅ <ø> (∅)
@tanstack/query-core 97.35% <93.75%> (-0.04%) ⬇️
@tanstack/query-devtools 3.48% <ø> (ø)
@tanstack/query-persist-client-core 80.00% <ø> (ø)
@tanstack/query-sync-storage-persister 84.61% <ø> (ø)
@tanstack/query-test-utils ∅ <ø> (∅)
@tanstack/react-query 96.01% <ø> (ø)
@tanstack/react-query-devtools 9.25% <ø> (ø)
@tanstack/react-query-next-experimental ∅ <ø> (∅)
@tanstack/react-query-persist-client 100.00% <ø> (ø)
@tanstack/solid-query 77.81% <ø> (ø)
@tanstack/solid-query-devtools 64.17% <ø> (ø)
@tanstack/solid-query-persist-client 100.00% <ø> (ø)
@tanstack/svelte-query ∅ <ø> (∅)
@tanstack/svelte-query-devtools ∅ <ø> (∅)
@tanstack/svelte-query-persist-client ∅ <ø> (∅)
@tanstack/vue-query 71.34% <0.00%> (-0.58%) ⬇️
@tanstack/vue-query-devtools ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@DogPawHat DogPawHat force-pushed the implement-simplified-imperitive-methods branch from b3a20d4 to 46d274c Compare November 1, 2025 20:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 411f030 and 46d274c.

📒 Files selected for processing (5)
  • .changeset/wise-suns-ask.md (1 hunks)
  • packages/query-core/src/__tests__/queryClient.test-d.tsx (2 hunks)
  • packages/query-core/src/__tests__/queryClient.test.tsx (9 hunks)
  • packages/query-core/src/queryClient.ts (6 hunks)
  • packages/vue-query/src/queryClient.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-19T03:18:18.303Z
Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test-d.tsx
📚 Learning: 2025-09-02T17:57:33.184Z
Learnt from: TkDodo
Repo: TanStack/query PR: 9612
File: packages/query-async-storage-persister/src/asyncThrottle.ts:0-0
Timestamp: 2025-09-02T17:57:33.184Z
Learning: When importing from tanstack/query-core in other TanStack Query packages like query-async-storage-persister, a workspace dependency "tanstack/query-core": "workspace:*" needs to be added to the package.json.

Applied to files:

  • .changeset/wise-suns-ask.md
🧬 Code graph analysis (4)
packages/query-core/src/__tests__/queryClient.test-d.tsx (3)
packages/query-core/src/types.ts (1)
  • InfiniteData (204-207)
packages/query-core/src/queryClient.ts (1)
  • infiniteQuery (395-417)
packages/vue-query/src/queryClient.ts (1)
  • infiniteQuery (328-346)
packages/query-core/src/__tests__/queryClient.test.tsx (2)
packages/query-core/src/utils.ts (2)
  • noop (82-82)
  • sleep (363-367)
packages/query-core/src/types.ts (1)
  • QueryFunction (96-100)
packages/vue-query/src/queryClient.ts (3)
packages/query-core/src/types.ts (5)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • FetchQueryOptions (491-507)
  • FetchInfiniteQueryOptions (548-565)
  • InfiniteData (204-207)
packages/vue-query/src/types.ts (1)
  • MaybeRefDeep (29-37)
packages/vue-query/src/utils.ts (1)
  • cloneDeepUnref (70-97)
packages/query-core/src/queryClient.ts (2)
packages/query-core/src/utils.ts (1)
  • noop (82-82)
packages/query-core/src/types.ts (5)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • FetchQueryOptions (491-507)
  • FetchInfiniteQueryOptions (548-565)
  • InfiniteData (204-207)
🪛 LanguageTool
.changeset/wise-suns-ask.md

[grammar] ~6-~6: Ensure spelling is correct
Context: ...tanstack/vue-query': minor --- renamed imperitive methods

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🔇 Additional comments (8)
packages/query-core/src/queryClient.ts (5)

140-159: LGTM! ensureQueryData correctly delegates to the new query method.

The internal delegation to query with staleTime: 'static' maintains the expected behavior while utilizing the new method.


336-365: Verify alignment with maintainer expectations regarding API migration strategy.

Per TkDodo's comment, the original intent was to "add new methods and deprecate the old ones to avoid a breaking change, not to remove/rename them outright." While this implementation maintains backward compatibility by keeping fetchQuery as a wrapper, please confirm that making query the primary implementation (rather than keeping fetchQuery as primary and adding query as an alias) aligns with the team's migration strategy.


384-393: LGTM! prefetchQuery correctly delegates to the new query method.

The delegation pattern with .then(noop).catch(noop) properly maintains the fire-and-forget prefetch behavior.


395-417: LGTM! infiniteQuery implementation is clean and consistent.

The method correctly sets the infiniteQueryBehavior and delegates to the query method. The type assertion on line 416 is necessary due to the behavior transformation.


436-452: LGTM! prefetchInfiniteQuery correctly delegates to the new infiniteQuery method.

The delegation pattern maintains the fire-and-forget prefetch behavior.

packages/query-core/src/__tests__/queryClient.test-d.tsx (1)

313-328: LGTM! Type assertions for new methods are comprehensive and correct.

The type checks for query and infiniteQuery methods properly cover both fully typed and untyped scenarios, maintaining consistency with the existing test structure.

Also applies to: 462-477

packages/query-core/src/__tests__/queryClient.test.tsx (1)

11-11: LGTM! Comprehensive test coverage for the new query methods.

The test additions are excellent:

  • Properly imports noop utility for prefetch patterns
  • Marks old test suites with @deprecated comments for clarity
  • Provides thorough coverage of new query and infiniteQuery methods including:
    • Static staleTime behavior
    • Prefetching scenarios
    • Type safety validation
    • Edge cases (cache hits, invalidation, GC, etc.)
  • Maintains parallel structure with legacy tests while validating new functionality

Also applies to: 453-453, 529-620, 622-622, 683-720, 753-753, 928-1100, 1102-1102, 1147-1189, 1191-1191, 1281-1374, 1376-1376, 1426-1477

packages/vue-query/src/queryClient.ts (1)

256-346: LGTM! Vue Query extensions for new methods are well-implemented.

The query and infiniteQuery methods properly:

  • Provide overloads for both plain and MaybeRefDeep options
  • Use cloneDeepUnref to handle Vue's reactive refs correctly
  • Delegate to the parent QueryClient implementation
  • Follow the established pattern used by other methods in this class

@DogPawHat
Copy link
Contributor Author

DogPawHat commented Nov 1, 2025

From #9135:

Per default, this should behave like queryClient.fetchQuery does today:

  • it respects staleTime (like any good query should)
  • it returns a Promise you can await.

fetchQuery is still there, it's just a straight passthough for query now

@DogPawHat DogPawHat force-pushed the implement-simplified-imperitive-methods branch from c18dfc0 to 7670b40 Compare November 2, 2025 13:08
initialPageParam: 1,
})

const data = await new QueryClient().infiniteQuery(options)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Known type failures here.

as far as I know a select pass into a useInfiniteQuery can transform the data: InfiniteData into whatever (e.g. an Array<>) and that will end up being the data returned from the infinite query*. infiniteQuery should do the same I think, but we've got a big type mismatch here at the moment.

*I suspect this is not the best idea

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type errors from my local VSCode:

Types of property 'select' are incompatible.
        Type '((data: InfiniteData<string, number>) => string[]) | undefined' is not assignable to type '((data: InfiniteData<string, number>) => string) | undefined'.
          Type '(data: InfiniteData<string, number>) => string[]' is not assignable to type '(data: InfiniteData<string, number>) => string'.
            Type 'string[]' is not assignable to type 'string'.ts(2345)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since it works for useInfiniteQuery, it should also work for client.infiniteQuery()

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 16bed21 and fb9dcdc.

📒 Files selected for processing (8)
  • .changeset/famous-owls-battle.md (1 hunks)
  • packages/query-core/src/__tests__/queryClient.test-d.tsx (7 hunks)
  • packages/query-core/src/__tests__/queryClient.test.tsx (9 hunks)
  • packages/query-core/src/queryClient.ts (8 hunks)
  • packages/query-core/src/types.ts (3 hunks)
  • packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx (3 hunks)
  • packages/react-query/src/__tests__/queryOptions.test-d.tsx (2 hunks)
  • packages/vue-query/src/queryClient.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/react-query/src/tests/queryOptions.test-d.tsx
  • packages/react-query/src/tests/infiniteQueryOptions.test-d.tsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-19T03:18:18.303Z
Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test-d.tsx
📚 Learning: 2025-09-02T17:57:33.184Z
Learnt from: TkDodo
Repo: TanStack/query PR: 9612
File: packages/query-async-storage-persister/src/asyncThrottle.ts:0-0
Timestamp: 2025-09-02T17:57:33.184Z
Learning: When importing from tanstack/query-core in other TanStack Query packages like query-async-storage-persister, a workspace dependency "tanstack/query-core": "workspace:*" needs to be added to the package.json.

Applied to files:

  • .changeset/famous-owls-battle.md
🧬 Code graph analysis (4)
packages/query-core/src/__tests__/queryClient.test-d.tsx (2)
packages/query-core/src/queryClient.ts (1)
  • infiniteQuery (409-431)
packages/query-core/src/types.ts (2)
  • InfiniteData (204-207)
  • InfiniteQueryExecuteOptions (568-586)
packages/query-core/src/queryClient.ts (4)
packages/query-core/src/utils.ts (2)
  • noop (82-82)
  • resolveStaleTime (101-113)
packages/query-core/src/types.ts (7)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • QueryExecuteOptions (491-509)
  • FetchQueryOptions (511-527)
  • InfiniteQueryExecuteOptions (568-586)
  • FetchInfiniteQueryOptions (588-605)
  • InfiniteData (204-207)
packages/query-core/src/query.ts (1)
  • isStale (296-306)
packages/vue-query/src/queryClient.ts (1)
  • query (294-314)
packages/query-core/src/__tests__/queryClient.test.tsx (2)
packages/query-core/src/utils.ts (2)
  • noop (82-82)
  • sleep (363-367)
packages/query-core/src/types.ts (1)
  • QueryFunction (96-100)
packages/vue-query/src/queryClient.ts (3)
packages/query-core/src/types.ts (5)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • QueryExecuteOptions (491-509)
  • InfiniteQueryExecuteOptions (568-586)
  • InfiniteData (204-207)
packages/vue-query/src/types.ts (1)
  • MaybeRefDeep (29-37)
packages/vue-query/src/utils.ts (1)
  • cloneDeepUnref (70-97)
🪛 Biome (2.1.2)
packages/query-core/src/__tests__/queryClient.test-d.tsx

[error] 342-342: Const declarations must have an initialized value.

This variable needs to be initialized.

(parse)


[error] 342-342: Shouldn't redeclare 'infiniteQueryOptions'. Consider to delete it or rename it.

'infiniteQueryOptions' is defined here:

(lint/suspicious/noRedeclare)


[error] 441-441: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 443-443: Shouldn't redeclare 'infiniteQuery'. Consider to delete it or rename it.

'infiniteQuery' is defined here:

(lint/suspicious/noRedeclare)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (7)
packages/query-core/src/__tests__/queryClient.test-d.tsx (7)

161-172: LGTM!

The test correctly verifies that fetchQuery does not accept the select option, maintaining backward compatibility as intended in the PR design.


174-227: LGTM!

The tests correctly verify:

  • select option is not allowed on fetchInfiniteQuery (backward compatibility)
  • pages parameter is properly typed
  • getNextPageParam is required when pages is specified

229-239: LGTM!

The test correctly verifies that the new query method accepts the select option, which is the key differentiator from the fetchQuery compatibility wrapper.


242-257: Verify whether select should be allowed on infiniteQuery.

This test asserts that select is not allowed on infiniteQuery, but:

  1. Lines 336-339 show InfiniteQueryExecuteOptions being used with a select option successfully
  2. Unlike the fetchInfiniteQuery test (line 183), there's no @ts-expect-error annotation on the select property (line 249)

Based on the implementation where infiniteQuery delegates to query (which supports select), it appears select should be allowed. Please clarify the intended behavior and add the @ts-expect-error annotation if select is truly not supported, or update the test description if it is supported.


428-429: LGTM!

The type check correctly verifies that query returns the expected TData type.


578-579: LGTM!

The type check correctly verifies that query returns unknown when called with untyped options.


583-593: LGTM!

The type checks correctly verify the return types for fetchInfiniteQuery and infiniteQuery with untyped options, both returning InfiniteData<unknown, unknown>.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fb9dcdc and 3b33d44.

📒 Files selected for processing (2)
  • .changeset/famous-owls-battle.md (1 hunks)
  • packages/query-core/src/__tests__/queryClient.test-d.tsx (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .changeset/famous-owls-battle.md
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-19T03:18:18.303Z
Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test-d.tsx
🧬 Code graph analysis (1)
packages/query-core/src/__tests__/queryClient.test-d.tsx (3)
packages/query-core/src/queryClient.ts (2)
  • QueryClient (63-692)
  • infiniteQuery (409-431)
packages/vue-query/src/queryClient.ts (2)
  • QueryClient (39-589)
  • infiniteQuery (348-366)
packages/query-core/src/types.ts (2)
  • InfiniteData (204-207)
  • InfiniteQueryExecuteOptions (568-586)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Preview
  • GitHub Check: Test

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b33d44 and a24433b.

📒 Files selected for processing (1)
  • packages/query-core/src/__tests__/queryClient.test-d.tsx (7 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.049Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.
📚 Learning: 2025-11-02T22:52:33.049Z
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.049Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test-d.tsx
📚 Learning: 2025-08-19T03:18:18.303Z
Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test-d.tsx
🧬 Code graph analysis (1)
packages/query-core/src/__tests__/queryClient.test-d.tsx (2)
packages/query-core/src/queryClient.ts (1)
  • infiniteQuery (409-431)
packages/query-core/src/types.ts (2)
  • InfiniteData (204-207)
  • InfiniteQueryExecuteOptions (568-586)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test
  • GitHub Check: Preview
🔇 Additional comments (5)
packages/query-core/src/__tests__/queryClient.test-d.tsx (5)

13-13: LGTM!

The addition of InfiniteQueryExecuteOptions to the imports aligns with the new public API surface introduced in this PR.


161-172: LGTM!

This test correctly validates that the legacy fetchQuery method does not support the select option, with proper use of @ts-expect-error to enforce the type constraint.


174-227: LGTM!

The tests for fetchInfiniteQuery correctly validate the legacy behavior, including:

  • Properly rejecting select option with @ts-expect-error
  • Validating the pages option with correct type expectations
  • Enforcing required parameter constraints

229-239: LGTM!

This test correctly validates that the new query method supports the select option for data transformation, properly demonstrating the enhanced functionality compared to the legacy fetchQuery.


328-336: LGTM!

The integration of the new query and infiniteQuery methods into the fully-typed and untyped test sections is correct:

  • Proper usage of InfiniteQueryExecuteOptions<TData, TError> type
  • Correct type expectations for return values
  • Good coverage of both typed and untyped variants

Also applies to: 422-423, 434-435, 569-570, 581-584

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/query-core/src/__tests__/queryClient.test-d.tsx (1)

205-214: Fix misleading test title.

The test uses assertType without @ts-expect-error, meaning it's verifying that passing getNextPageParam without pages is allowed (per the InfiniteQueryPages union's { pages?: never } branch). The title incorrectly says "should not allow".

Apply this diff:

-  it('should not allow passing getNextPageParam without pages', () => {
+  it('should allow passing getNextPageParam without pages', () => {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a24433b and fa6f86f.

📒 Files selected for processing (2)
  • packages/query-core/src/__tests__/queryClient.test-d.tsx (7 hunks)
  • packages/query-core/src/types.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.049Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.
📚 Learning: 2025-11-02T22:52:33.049Z
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.049Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/query-core/src/types.ts
📚 Learning: 2025-08-19T03:18:18.303Z
Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/query-core/src/types.ts
🧬 Code graph analysis (1)
packages/query-core/src/__tests__/queryClient.test-d.tsx (2)
packages/query-core/src/queryClient.ts (1)
  • infiniteQuery (409-431)
packages/query-core/src/types.ts (2)
  • InfiniteData (204-207)
  • InfiniteQueryExecuteOptions (568-586)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Test
  • GitHub Check: Preview
🔇 Additional comments (7)
packages/query-core/src/types.ts (3)

491-509: LGTM: QueryExecuteOptions introduces select support correctly.

The new QueryExecuteOptions interface properly introduces the select transformation flow via the TQueryData generic. The data flows as TQueryFnData (raw) → TQueryData (intermediate) → TData (final via select). The staleTime correctly uses TQueryData since staleness should be determined from the query's stored data, not the transformed result.


511-528: LGTM: FetchQueryOptions maintains backward compatibility.

The refactor to make FetchQueryOptions an alias that omits select from QueryExecuteOptions is correct. Passing TData as both the 3rd and 4th generics (TData, TData) ensures no transformation layer exists when select is omitted, maintaining the original behavior of fetchQuery.


568-586: LGTM: InfiniteQueryExecuteOptions properly extends execute options.

The type correctly:

  • Omits initialPageParam from QueryExecuteOptions (which has initialPageParam?: never)
  • Re-adds it via InitialPageParam<TPageParam> with the proper type
  • Uses InfiniteData<TQueryFnData, TPageParam> as the intermediate data shape
  • Includes InfiniteQueryPages discriminated union to enforce the pages/getNextPageParam constraint
packages/query-core/src/__tests__/queryClient.test-d.tsx (4)

161-172: LGTM: Correctly verifies fetchQuery rejects select.

The test properly uses @ts-expect-error to confirm that the legacy fetchQuery method does not support the select option, maintaining backward compatibility.

Based on learnings.


229-239: LGTM: Correctly verifies query accepts select.

The test confirms that the new query method supports the select option for data transformation, using assertType (without @ts-expect-error) to validate this is allowed.

Based on learnings.


241-257: LGTM: Correctly verifies infiniteQuery accepts select.

The test confirms that the new infiniteQuery method supports the select option for transforming infinite query data, using assertType (without @ts-expect-error) to validate this is allowed.

Based on learnings.


328-336: LGTM: infiniteQueryOptions properly typed.

The variable correctly uses InfiniteQueryExecuteOptions<TData, TError> with defaults for remaining generics. The getNextPageParam callback properly receives lastPage typed as TData.

Comment on lines 150 to 154
const cachedData = query.state.data

if (cachedData === undefined) {
return this.fetchQuery(options)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get why this was removed (because staleTime: 'static' achieves the same thing), however, background refetching with revalidateIfStale was never triggered if we had no data in the cache, and right now, it’s the first thing that happens.

I guess it’s mostly fine because query.fetch will dedupe promises, but there is the edge-case where users pass cancelRefetch which would lead to to the first fetch being cancelled.

Not sure what a good way out here would be, except maybe not re-implement ensureQueryData with this.query rather than keep the current implementation ?

also since query now supports select, these functions also do transformation in case you’ve passed excess properties!

I think what we should do is leave ensureQueryData, fetchQuery and prefetchQuery alone for now and NOT have them call .query or .infiniteQuery under the hood.

return basePromise.then((data) => select(data))
}

return basePromise.then((data) => data as unknown as TData)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why this is necessary :/

initialPageParam: 1,
})

const data = await new QueryClient().infiniteQuery(options)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since it works for useInfiniteQuery, it should also work for client.infiniteQuery()

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/query-core/src/queryClient.ts (1)

428-450: Implementation delegates correctly, but consider type-safe alternatives to the cast.

The method properly sets infiniteQueryBehavior before delegating to query. The as any cast on line 449 bypasses type safety—consider whether tighter generic constraints or a helper could eliminate it.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fa6f86f and 6a3c2ed.

📒 Files selected for processing (2)
  • packages/query-core/src/queryClient.ts (5 hunks)
  • packages/query-core/src/types.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.
📚 Learning: 2025-11-02T22:52:33.071Z
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.

Applied to files:

  • packages/query-core/src/types.ts
  • packages/query-core/src/queryClient.ts
🧬 Code graph analysis (1)
packages/query-core/src/queryClient.ts (3)
packages/query-core/src/types.ts (6)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • QueryExecuteOptions (491-509)
  • InfiniteQueryExecuteOptions (568-586)
  • FetchInfiniteQueryOptions (588-605)
  • InfiniteData (204-207)
packages/vue-query/src/queryClient.ts (1)
  • query (294-314)
packages/query-core/src/utils.ts (1)
  • resolveStaleTime (101-113)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (4)
packages/query-core/src/types.ts (2)

491-509: LGTM! Well-designed interface for query execution options.

The interface correctly separates TQueryData from TData to enable optional select transformation, explicitly prevents initialPageParam for single queries, and provides clear documentation for staleTime behavior.


561-586: LGTM! Clean type composition for infinite query execution.

The discriminated union for InfiniteQueryPages and the composition strategy for InfiniteQueryExecuteOptions (omitting the never field then adding the required version) correctly enforces that infinite queries must provide initialPageParam.

packages/query-core/src/queryClient.ts (2)

343-384: LGTM! Core query execution logic is sound.

The method correctly handles stale-time checking, optional data fetching, and select transformation. The double cast as unknown as TData on line 383 is a TypeScript workaround when no select is provided (TData defaults to TQueryData), though it's safe in practice.


452-468: Fix: Missing options.behavior setup before delegation to fetchQuery.

The fetchInfiniteQuery method must set options.behavior before delegating to fetchQuery, matching the pattern used in infiniteQuery (lines 443-448) and ensureInfiniteQueryData (lines 503-508). Without this, infinite query pagination will not work correctly.

 fetchInfiniteQuery<
   TQueryFnData,
   TError = DefaultError,
   TData = TQueryFnData,
   TQueryKey extends QueryKey = QueryKey,
   TPageParam = unknown,
 >(
   options: FetchInfiniteQueryOptions<
     TQueryFnData,
     TError,
     TData,
     TQueryKey,
     TPageParam
   >,
 ): Promise<InfiniteData<TData, TPageParam>> {
+  options.behavior = infiniteQueryBehavior<
+    TQueryFnData,
+    TError,
+    TData,
+    TPageParam
+  >(options.pages)
   return this.fetchQuery(options as any)
 }
⛔ Skipped due to learnings
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/query-core/src/queryClient.ts (1)

428-450: Fix the type error and avoid as any assertion.

Two issues need to be addressed:

  1. Pipeline failure (Line 443): The type error indicates that QueryBehavior<TQueryFnData, TError, InfiniteData<TQueryFnData, TPageParam>, readonly unknown[]> is not assignable to QueryBehavior<TQueryFnData, TError, InfiniteData<TQueryFnData, TPageParam>, TQueryKey>. This suggests a mismatch in the query key type constraint.

  2. Line 449: The as any type assertion bypasses type safety and hides potential type errors. This indicates that the types don't align properly between InfiniteQueryExecuteOptions and QueryExecuteOptions.

The type system should properly model the relationship between these option types without requiring unsafe casts. Please investigate:

  • Whether the QueryExecuteOptions type needs to be adjusted to properly accept infinite query options
  • Whether the generic constraints need to be refined to make the types compatible
  • Alternative approaches that maintain type safety
#!/bin/bash
# Check how behavior property is typed and used
ast-grep --pattern $'behavior: QueryBehavior<$$$>'
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a3c2ed and 1338e8e.

📒 Files selected for processing (1)
  • packages/query-core/src/queryClient.ts (5 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.
📚 Learning: 2025-11-02T22:52:33.071Z
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.

Applied to files:

  • packages/query-core/src/queryClient.ts
🧬 Code graph analysis (1)
packages/query-core/src/queryClient.ts (3)
packages/query-core/src/types.ts (6)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • QueryExecuteOptions (491-509)
  • InfiniteQueryExecuteOptions (568-586)
  • FetchInfiniteQueryOptions (588-605)
  • InfiniteData (204-207)
packages/vue-query/src/queryClient.ts (1)
  • query (294-314)
packages/query-core/src/utils.ts (1)
  • resolveStaleTime (101-113)
🪛 GitHub Actions: PR
packages/query-core/src/queryClient.ts

[error] 443-443: Type 'QueryBehavior<TQueryFnData, TError, InfiniteData<TQueryFnData, TPageParam>, readonly unknown[]>' is not assignable to type 'QueryBehavior<TQueryFnData, TError, InfiniteData<TQueryFnData, TPageParam>, TQueryKey>'.

🔇 Additional comments (2)
packages/query-core/src/queryClient.ts (2)

28-28: LGTM!

The new type imports support the query and infiniteQuery method signatures correctly.

Also applies to: 37-37


373-383: Verify data handling assumptions in the query method implementation.

The technical concerns in the review are valid: when isStale is false, query.state.data could be undefined (initialized without initialData), and this would be passed to the select function without a guard. The type signature select?: (data: TQueryData) => TData expects defined data, but the cast on line 375 (as TQueryData) doesn't guarantee it at runtime.

However, test cases across the codebase show select always receives properly typed, defined data—no scenario in tests passes undefined to the selector. This suggests either:

  1. The scenario is prevented by caller contracts (e.g., always providing initialData or ensuring fetch completes first)
  2. The stale-time logic prevents isStale=false when data is undefined
  3. This is an edge case not covered by tests

Confirm whether adding a guard (e.g., if (!queryData) return queryData as TData) is necessary, or if the current design intentionally relies on caller responsibility to provide valid initial state.

Comment on lines 452 to 478
fetchInfiniteQuery<
TQueryFnData,
TError = DefaultError,
TData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = unknown,
>(
options: FetchInfiniteQueryOptions<
TQueryFnData,
TError,
TData,
TQueryKey,
TPageParam
>,
): Promise<InfiniteData<TData, TPageParam>> {
return this.fetchQuery(options as any)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Avoid as any type assertion.

Line 467 uses as any when delegating to fetchQuery, which bypasses type safety. While this maintains the existing delegation pattern (based on past review comments indicating fetchInfiniteQuery should call fetchQuery), the type assertion suggests that FetchInfiniteQueryOptions and FetchQueryOptions aren't properly aligned.

Consider:

  • Ensuring FetchInfiniteQueryOptions properly extends or is compatible with FetchQueryOptions so no cast is needed
  • Adding an internal helper that both methods can safely delegate to without type assertions
  • If the cast is unavoidable due to the type structure, document why it's safe with a comment
#!/bin/bash
# Check the relationship between FetchInfiniteQueryOptions and FetchQueryOptions
ast-grep --pattern $'export type FetchInfiniteQueryOptions<$$$> = $$$'
🤖 Prompt for AI Agents
In packages/query-core/src/queryClient.ts around lines 452 to 468, the
fetchInfiniteQuery implementation uses "as any" to call fetchQuery which
bypasses type safety; fix by ensuring FetchInfiniteQueryOptions is compatible
with FetchQueryOptions (update its declaration to extend or intersect the
FetchQueryOptions generic shape), or extract a private internal typed helper
that both fetchQuery and fetchInfiniteQuery call (with appropriate generic
bounds) so no cast is needed; if a cast is truly unavoidable due to type
constraints, replace "as any" with a narrower, justified cast and add a brief
comment explaining why the cast is safe.

@DogPawHat DogPawHat force-pushed the implement-simplified-imperitive-methods branch from 1338e8e to 8c46d9e Compare November 26, 2025 14:56
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/query-core/src/queryClient.ts (1)

428-452: Restore infiniteQueryBehavior wiring for fetchInfiniteQuery and reduce as any surface

Currently, only infiniteQuery and ensureInfiniteQueryData attach infiniteQueryBehavior, while fetchInfiniteQuery now delegates straight to fetchQuery without setting options.behavior:

fetchInfiniteQuery(...) {
  return this.fetchQuery(options as any)
}

In the published build, fetchInfiniteQuery sets options.behavior = infiniteQueryBehavior(options.pages) before calling fetchQuery, which is what gives it proper infinite paging semantics (using pages, pageParams, and getNextPageParam). (impactic.de) Dropping that here likely breaks existing fetchInfiniteQuery behavior and will make tests like “should return infinite query data”/“should prefetch multiple pages” incorrect at runtime.

I’d strongly suggest restoring the behavior setup, e.g.:

  fetchInfiniteQuery<
    TQueryFnData,
    TError = DefaultError,
    TData = TQueryFnData,
    TQueryKey extends QueryKey = QueryKey,
    TPageParam = unknown,
  >(
    options: FetchInfiniteQueryOptions<
      TQueryFnData,
      TError,
      TData,
      TQueryKey,
      TPageParam
    >,
  ): Promise<InfiniteData<TData, TPageParam>> {
    options.behavior = infiniteQueryBehavior<
      TQueryFnData,
      TError,
      TData,
      TPageParam
    >(options.pages)
    return this.fetchQuery(options as any)
  }

On top of that, the three as any casts (this.query(options as any), this.fetchQuery(options as any), this.ensureQueryData(options as any)) are understandable given the generic differences between execute/fetch option types, but they do punch a hole through type safety. If feasible, consider a small internal helper or tightening the generic relationships between QueryExecuteOptions, InfiniteQueryExecuteOptions, FetchQueryOptions, and FetchInfiniteQueryOptions so these calls can be expressed without any (or at least with a narrower cast and a brief comment on why it’s safe).

Also applies to: 470-486, 488-511

🧹 Nitpick comments (1)
packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx (1)

53-66: Type tests correctly encode select behavior for infinite paths

The new tests nicely capture the intended distinctions:

  • useInfiniteQuery, useSuspenseInfiniteQuery, and QueryClient.infiniteQuery all see select and return the transformed Array<string> type.
  • fetchInfiniteQuery still yields InfiniteData<string, number> even when given options that include select, matching the legacy “no select” behavior for fetch APIs.

Only tiny nit: the “known issue” comment in the suspense test still mentions useInfiniteQuery, but that’s cosmetic.

Also applies to: 79-92, 93-117, 130-142

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1338e8e and 8c46d9e.

📒 Files selected for processing (8)
  • .changeset/famous-owls-battle.md (1 hunks)
  • packages/query-core/src/__tests__/queryClient.test-d.tsx (7 hunks)
  • packages/query-core/src/__tests__/queryClient.test.tsx (9 hunks)
  • packages/query-core/src/queryClient.ts (5 hunks)
  • packages/query-core/src/types.ts (3 hunks)
  • packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx (3 hunks)
  • packages/react-query/src/__tests__/queryOptions.test-d.tsx (2 hunks)
  • packages/vue-query/src/queryClient.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .changeset/famous-owls-battle.md
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.
📚 Learning: 2025-11-22T09:06:05.219Z
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Applied to files:

  • packages/react-query/src/__tests__/queryOptions.test-d.tsx
  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx
  • packages/query-core/src/__tests__/queryClient.test.tsx
  • packages/query-core/src/queryClient.ts
  • packages/vue-query/src/queryClient.ts
📚 Learning: 2025-11-02T22:52:33.071Z
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.

Applied to files:

  • packages/react-query/src/__tests__/queryOptions.test-d.tsx
  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx
  • packages/query-core/src/__tests__/queryClient.test.tsx
  • packages/query-core/src/queryClient.ts
  • packages/vue-query/src/queryClient.ts
  • packages/query-core/src/types.ts
📚 Learning: 2025-08-19T03:18:18.303Z
Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

Applied to files:

  • packages/react-query/src/__tests__/queryOptions.test-d.tsx
  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx
  • packages/query-core/src/queryClient.ts
🧬 Code graph analysis (3)
packages/query-core/src/__tests__/queryClient.test-d.tsx (1)
packages/query-core/src/types.ts (2)
  • InfiniteData (204-207)
  • InfiniteQueryExecuteOptions (568-586)
packages/query-core/src/queryClient.ts (2)
packages/query-core/src/types.ts (6)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • QueryExecuteOptions (491-509)
  • InfiniteQueryExecuteOptions (568-586)
  • FetchInfiniteQueryOptions (588-605)
  • InfiniteData (204-207)
packages/query-core/src/utils.ts (1)
  • resolveStaleTime (112-124)
packages/vue-query/src/queryClient.ts (3)
packages/query-core/src/types.ts (5)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • QueryExecuteOptions (491-509)
  • InfiniteQueryExecuteOptions (568-586)
  • InfiniteData (204-207)
packages/vue-query/src/types.ts (1)
  • MaybeRefDeep (29-37)
packages/vue-query/src/utils.ts (1)
  • cloneDeepUnref (70-97)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (8)
packages/query-core/src/types.ts (1)

491-509: New execute option types align well with observer options and infinite semantics

QueryExecuteOptions and InfiniteQueryExecuteOptions are wired correctly: using TQueryData for staleTime and select matches how defaultQueryOptions and resolveStaleTime operate, and InfiniteQueryPages cleanly enforces the pages/getNextPageParam pairing while being reused by both execute and fetch infinite options. This should give query/infiniteQuery the right type-level behavior without impacting existing Fetch* callers.

Also applies to: 561-587, 588-605

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

58-66: query vs fetchQuery select behavior is well covered

The added tests clearly distinguish the new query API (including select transformations) from the legacy fetchQuery (which returns the raw number even when given options that contain select). This matches the intended separation between the new and old imperative entry points.

Also applies to: 76-95

packages/query-core/src/__tests__/queryClient.test-d.tsx (2)

161-172: Type tests cleanly separate select support between legacy and new APIs

The new blocks for fetchQuery, fetchInfiniteQuery, query, and infiniteQuery correctly encode the contract:

  • fetchQuery/fetchInfiniteQuery reject select at the option level via @ts-expect-error.
  • query/infiniteQuery accept select and assert the transformed data types.

This gives solid type-level coverage for the migration story from the old fetch* APIs to the new imperative methods.

Also applies to: 175-192, 229-257


193-203: Infinite execute/fetch options generics are exercised thoroughly

The updated tests around passing pages, using { count: number } pages, and the “fully typed usage” blocks validate that:

  • FetchInfiniteQueryOptions and InfiniteQueryExecuteOptions expose lastPage as TData in getNextPageParam.
  • infiniteQuery and fetchInfiniteQuery both resolve to InfiniteData<TData, TPageParam> (or InfiniteData<unknown, unknown> in the untyped case).

This gives good confidence that the new infinite-execute types integrate correctly with QueryClient’s generics.

Also applies to: 259-269, 328-337, 422-435, 569-585

packages/query-core/src/__tests__/queryClient.test.tsx (2)

529-620: Static staleTime behavior for query/infiniteQuery is well specified

The new “with static staleTime” suites for both query and infiniteQuery clearly pin down the behavior:

  • Cached data (including falsy values) is returned without re-fetching when staleTime is 'static'.
  • Missing queries invoke queryFn once.
  • Providing initialData short-circuits network calls.
  • A second call with staleTime: 0 drives an explicit background revalidation, as verified via noop and cache assertions.

This is a strong regression suite for the new imperative surface.

Also applies to: 683-720


928-1106: Runtime tests give good confidence in new query/infiniteQuery entry points

The added query/infiniteQuery suites (including “used for prefetching”) thoroughly mirror the legacy fetchQuery/prefetch* behavior:

  • No-retry-by-default semantics, gcTime handling, and static staleTime cache hits are preserved.
  • Infinite flows still produce the expected InfiniteData shapes, including multi-page prefetch and early termination via getNextPageParam.
  • Prefetch-style usages (.catch(noop)) ensure that using query/infiniteQuery purely for seeding the cache continues to work.

Overall, the tests look well aligned with the intended migration path from the deprecated fetch* methods to the new APIs.

Also applies to: 1153-1195, 1287-1380, 1432-1483

packages/vue-query/src/queryClient.ts (1)

19-37: Vue QueryClient query/infiniteQuery wrappers are consistent and type-safe

The new query and infiniteQuery overloads:

  • Reuse the core QueryExecuteOptions / InfiniteQueryExecuteOptions generics correctly.
  • Preserve the Vue adapter’s MaybeRefDeep + cloneDeepUnref pattern so refs and getter-based queryKeys are handled before delegating.
  • Return the expected Promise<TData> / Promise<InfiniteData<TData, TPageParam>> types, matching the core client.

This keeps the Vue surface in lockstep with the new imperative APIs.

Also applies to: 258-366

packages/query-core/src/queryClient.ts (1)

343-384: query implementation correctly layers select on top of legacy fetch semantics

The new query method:

  • Runs through defaultQueryOptions, preserves the “no retry by default” behavior from fetchQuery, and uses resolveStaleTime with QueryExecuteOptions.staleTime typed on TQueryData.
  • Fetches when isStaleByTime is true, otherwise returns query.state.data from cache.
  • Applies select once, purely at the imperative layer, without mutating the stored query data.

This matches the intended contract for the new imperative API and is well covered by the added runtime and type tests.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
packages/query-core/src/queryClient.ts (1)

428-454: Type assertion bypasses type safety.

Line 453 uses as any when delegating to this.query, which bypasses TypeScript's type checking. While this mirrors the existing pattern in fetchInfiniteQuery (Line 477), the cast suggests that InfiniteQueryExecuteOptions and QueryExecuteOptions aren't properly aligned.

Consider refactoring to eliminate the cast by:

  • Ensuring type compatibility between the two option types
  • Extracting a shared internal helper that both methods can call with appropriate generic bounds
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c46d9e and a16e585.

📒 Files selected for processing (3)
  • packages/query-core/src/queryClient.ts (4 hunks)
  • packages/query-core/src/types.ts (3 hunks)
  • packages/vue-query/src/queryClient.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.
📚 Learning: 2025-11-02T22:52:33.071Z
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.

Applied to files:

  • packages/query-core/src/queryClient.ts
  • packages/query-core/src/types.ts
  • packages/vue-query/src/queryClient.ts
📚 Learning: 2025-11-22T09:06:05.219Z
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Applied to files:

  • packages/query-core/src/queryClient.ts
  • packages/vue-query/src/queryClient.ts
📚 Learning: 2025-08-19T03:18:18.303Z
Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

Applied to files:

  • packages/query-core/src/queryClient.ts
🧬 Code graph analysis (1)
packages/query-core/src/queryClient.ts (4)
packages/query-core/src/types.ts (5)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • QueryExecuteOptions (491-509)
  • InfiniteData (204-207)
  • InfiniteQueryExecuteOptions (568-586)
packages/query-core/src/query.ts (1)
  • isStale (296-306)
packages/query-core/src/utils.ts (1)
  • resolveStaleTime (112-124)
packages/query-core/src/infiniteQueryBehavior.ts (1)
  • infiniteQueryBehavior (11-133)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Preview
  • GitHub Check: Test
🔇 Additional comments (2)
packages/query-core/src/queryClient.ts (1)

343-384: LGTM! The query method logic is sound.

The implementation correctly:

  • Defaults retry to false (matching fetchQuery behavior)
  • Checks staleness via resolveStaleTime
  • Fetches when stale or returns cached data
  • Applies select transformation when provided

The double cast at Line 383 (as unknown as TData) is safe given that TData defaults to TQueryData when select is not provided, though it's overly defensive.

Based on learnings, the new query method correctly supports the select option for data transformation.

packages/query-core/src/types.ts (1)

491-509: LGTM! Type definitions are well-structured.

The new type definitions are correctly designed:

  • QueryExecuteOptions (491-509): Properly extends QueryOptions with required queryKey, adds select for data transformation, and includes staleTime for staleness control
  • InfiniteQueryPages (561-566): Clean discriminated union that allows optional pages specification or requires getNextPageParam when pages are specified
  • InfiniteQueryExecuteOptions (568-586): Well-composed type combining QueryExecuteOptions, InitialPageParam, and InfiniteQueryPages
  • FetchInfiniteQueryOptions (605): Updated to reuse InfiniteQueryPages, improving consistency

Based on learnings, the new types correctly support the select option for data transformation in query and infiniteQuery methods.

Also applies to: 561-586, 605-605

Comment on lines +275 to +312
query<
TQueryFnData,
TError = DefaultError,
TData = TQueryFnData,
TQueryData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = never,
>(
options: MaybeRefDeep<
QueryExecuteOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey,
TPageParam
>
>,
): Promise<TData>
query<
TQueryFnData,
TError = DefaultError,
TData = TQueryFnData,
TQueryData = TQueryFnData,
TQueryKey extends QueryKey = QueryKey,
TPageParam = never,
>(
options: MaybeRefDeep<
QueryExecuteOptions<
TQueryFnData,
TError,
TData,
TQueryData,
TQueryKey,
TPageParam
>
>,
): Promise<TData> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove duplicate overload.

The second and third overloads for the query method (Lines 275-293 and 294-312) are identical—they have the same generic parameters, option type, and return type. TypeScript does not allow duplicate overload signatures.

Remove one of the duplicate overloads:

   ): Promise<TData>
   query<
     TQueryFnData,
     TError = DefaultError,
     TData = TQueryFnData,
     TQueryData = TQueryFnData,
     TQueryKey extends QueryKey = QueryKey,
     TPageParam = never,
   >(
     options: MaybeRefDeep<
       QueryExecuteOptions<
         TQueryFnData,
         TError,
         TData,
         TQueryData,
         TQueryKey,
         TPageParam
       >
     >,
   ): Promise<TData>
-  query<
-    TQueryFnData,
-    TError = DefaultError,
-    TData = TQueryFnData,
-    TQueryData = TQueryFnData,
-    TQueryKey extends QueryKey = QueryKey,
-    TPageParam = never,
-  >(
-    options: MaybeRefDeep<
-      QueryExecuteOptions<
-        TQueryFnData,
-        TError,
-        TData,
-        TQueryData,
-        TQueryKey,
-        TPageParam
-      >
-    >,
-  ): Promise<TData> {
+  query<TQueryFnData, TError = DefaultError, TData = TQueryFnData, TQueryData = TQueryFnData, TQueryKey extends QueryKey = QueryKey, TPageParam = never>(options: MaybeRefDeep<QueryExecuteOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey, TPageParam>>): Promise<TData> {
     return super.query(cloneDeepUnref(options))
   }
🤖 Prompt for AI Agents
packages/vue-query/src/queryClient.ts around lines 275 to 312: there are
duplicate overload signatures for the query method (the overloads covering lines
275-293 and 294-312 are identical), which causes a TypeScript duplicate overload
error; remove one of the identical overload declarations so only a single
overload (followed by the implementation) remains, ensuring generics, parameter
types, and return type are preserved exactly in the kept signature.

Comment on lines +335 to +376
infiniteQuery<
TQueryFnData,
TError = DefaultError,
TData = InfiniteData<TQueryFnData>,
TQueryKey extends QueryKey = QueryKey,
TPageParam = unknown,
>(
options: MaybeRefDeep<
InfiniteQueryExecuteOptions<
TQueryFnData,
TError,
TData,
TQueryKey,
TPageParam
>
>,
): Promise<
Array<TData> extends Array<InfiniteData<TQueryFnData>>
? InfiniteData<TQueryFnData, TPageParam>
: TData
>
infiniteQuery<
TQueryFnData,
TError = DefaultError,
TData = InfiniteData<TQueryFnData>,
TQueryKey extends QueryKey = QueryKey,
TPageParam = unknown,
>(
options: MaybeRefDeep<
InfiniteQueryExecuteOptions<
TQueryFnData,
TError,
TData,
TQueryKey,
TPageParam
>
>,
): Promise<
Array<TData> extends Array<InfiniteData<TQueryFnData>>
? InfiniteData<TQueryFnData, TPageParam>
: TData
> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Remove duplicate overload.

The second and third overloads for the infiniteQuery method (Lines 335-355 and 356-376) are identical. This is the same duplication issue as the query method.

Remove one of the duplicate overloads:

   >
   infiniteQuery<
     TQueryFnData,
     TError = DefaultError,
     TData = InfiniteData<TQueryFnData>,
     TQueryKey extends QueryKey = QueryKey,
     TPageParam = unknown,
   >(
     options: MaybeRefDeep<
       InfiniteQueryExecuteOptions<
         TQueryFnData,
         TError,
         TData,
         TQueryKey,
         TPageParam
       >
     >,
   ): Promise<
     Array<TData> extends Array<InfiniteData<TQueryFnData>>
       ? InfiniteData<TQueryFnData, TPageParam>
       : TData
   >
-  infiniteQuery<
-    TQueryFnData,
-    TError = DefaultError,
-    TData = InfiniteData<TQueryFnData>,
-    TQueryKey extends QueryKey = QueryKey,
-    TPageParam = unknown,
-  >(
-    options: MaybeRefDeep<
-      InfiniteQueryExecuteOptions<
-        TQueryFnData,
-        TError,
-        TData,
-        TQueryKey,
-        TPageParam
-      >
-    >,
-  ): Promise<
-    Array<TData> extends Array<InfiniteData<TQueryFnData>>
-      ? InfiniteData<TQueryFnData, TPageParam>
-      : TData
-  > {
+  infiniteQuery<TQueryFnData, TError = DefaultError, TData = InfiniteData<TQueryFnData>, TQueryKey extends QueryKey = QueryKey, TPageParam = unknown>(options: MaybeRefDeep<InfiniteQueryExecuteOptions<TQueryFnData, TError, TData, TQueryKey, TPageParam>>): Promise<Array<TData> extends Array<InfiniteData<TQueryFnData>> ? InfiniteData<TQueryFnData, TPageParam> : TData> {
     return super.infiniteQuery(cloneDeepUnref(options))
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
infiniteQuery<
TQueryFnData,
TError = DefaultError,
TData = InfiniteData<TQueryFnData>,
TQueryKey extends QueryKey = QueryKey,
TPageParam = unknown,
>(
options: MaybeRefDeep<
InfiniteQueryExecuteOptions<
TQueryFnData,
TError,
TData,
TQueryKey,
TPageParam
>
>,
): Promise<
Array<TData> extends Array<InfiniteData<TQueryFnData>>
? InfiniteData<TQueryFnData, TPageParam>
: TData
>
infiniteQuery<
TQueryFnData,
TError = DefaultError,
TData = InfiniteData<TQueryFnData>,
TQueryKey extends QueryKey = QueryKey,
TPageParam = unknown,
>(
options: MaybeRefDeep<
InfiniteQueryExecuteOptions<
TQueryFnData,
TError,
TData,
TQueryKey,
TPageParam
>
>,
): Promise<
Array<TData> extends Array<InfiniteData<TQueryFnData>>
? InfiniteData<TQueryFnData, TPageParam>
: TData
> {
infiniteQuery<
TQueryFnData,
TError = DefaultError,
TData = InfiniteData<TQueryFnData>,
TQueryKey extends QueryKey = QueryKey,
TPageParam = unknown,
>(
options: MaybeRefDeep<
InfiniteQueryExecuteOptions<
TQueryFnData,
TError,
TData,
TQueryKey,
TPageParam
>
>,
): Promise<
Array<TData> extends Array<InfiniteData<TQueryFnData>>
? InfiniteData<TQueryFnData, TPageParam>
: TData
> {
return super.infiniteQuery(cloneDeepUnref(options))
}
🤖 Prompt for AI Agents
In packages/vue-query/src/queryClient.ts around lines 335 to 376, there are two
identical overload declarations for the infiniteQuery method; remove one of the
duplicate overload blocks (either the second or third of the two identical
signatures) so only a single overload remains before the implementation, then
run TypeScript type-check/build and tests to confirm no signature regressions.

TQueryFnData,
TError = DefaultError,
TData = TQueryFnData,
TData = InfiniteData<TQueryFnData>,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to match the options used by react query queryOptions but not InfiniteQueryObserverOptions in query-core types.ts.

@DogPawHat DogPawHat force-pushed the implement-simplified-imperitive-methods branch from be836cd to bf15113 Compare November 27, 2025 21:00
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/query-core/src/queryClient.ts (1)

471-477: Same as any pattern in fetchInfiniteQuery.

This follows the same pattern as infiniteQuery. Consistent with past review feedback, the cast exists due to type structure differences.

🧹 Nitpick comments (1)
packages/query-core/src/queryClient.ts (1)

447-453: The as any cast bypasses type checking.

The infiniteQuery method uses as any when delegating to this.query(). This is flagged as a concern in past reviews. While necessary due to the type complexity between InfiniteQueryExecuteOptions and QueryExecuteOptions, it could mask type errors.

Consider adding a brief inline comment explaining why the cast is safe:

     options.behavior = infiniteQueryBehavior<
       TQueryFnData,
       TError,
       TQueryFnData,
       TPageParam
     >(options.pages)
+    // Cast is safe: InfiniteQueryExecuteOptions extends QueryExecuteOptions with infinite-specific fields
     return this.query(options as any)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be836cd and bf15113.

📒 Files selected for processing (8)
  • .changeset/famous-owls-battle.md (1 hunks)
  • packages/query-core/src/__tests__/queryClient.test-d.tsx (7 hunks)
  • packages/query-core/src/__tests__/queryClient.test.tsx (9 hunks)
  • packages/query-core/src/queryClient.ts (4 hunks)
  • packages/query-core/src/types.ts (3 hunks)
  • packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx (3 hunks)
  • packages/react-query/src/__tests__/queryOptions.test-d.tsx (2 hunks)
  • packages/vue-query/src/queryClient.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • .changeset/famous-owls-battle.md
  • packages/react-query/src/tests/queryOptions.test-d.tsx
  • packages/react-query/src/tests/infiniteQueryOptions.test-d.tsx
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.
📚 Learning: 2025-11-22T09:06:05.219Z
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test.tsx
  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/query-core/src/queryClient.ts
  • packages/vue-query/src/queryClient.ts
📚 Learning: 2025-11-02T22:52:33.071Z
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test.tsx
  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/query-core/src/queryClient.ts
  • packages/query-core/src/types.ts
  • packages/vue-query/src/queryClient.ts
📚 Learning: 2025-08-19T03:18:18.303Z
Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test.tsx
  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/query-core/src/queryClient.ts
🧬 Code graph analysis (4)
packages/query-core/src/__tests__/queryClient.test.tsx (1)
packages/query-core/src/utils.ts (2)
  • noop (93-93)
  • sleep (374-378)
packages/query-core/src/__tests__/queryClient.test-d.tsx (1)
packages/query-core/src/types.ts (2)
  • InfiniteData (204-207)
  • InfiniteQueryExecuteOptions (568-586)
packages/query-core/src/queryClient.ts (4)
packages/query-core/src/types.ts (5)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • QueryExecuteOptions (491-509)
  • InfiniteData (204-207)
  • InfiniteQueryExecuteOptions (568-586)
packages/query-core/src/query.ts (1)
  • isStale (296-306)
packages/query-core/src/utils.ts (1)
  • resolveStaleTime (112-124)
packages/query-core/src/infiniteQueryBehavior.ts (1)
  • infiniteQueryBehavior (11-133)
packages/vue-query/src/queryClient.ts (3)
packages/query-core/src/types.ts (5)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • QueryExecuteOptions (491-509)
  • InfiniteData (204-207)
  • InfiniteQueryExecuteOptions (568-586)
packages/vue-query/src/types.ts (1)
  • MaybeRefDeep (29-37)
packages/vue-query/src/utils.ts (1)
  • cloneDeepUnref (70-97)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Test
🔇 Additional comments (16)
packages/query-core/src/__tests__/queryClient.test-d.tsx (5)

161-172: LGTM — Correctly verifies select is rejected for fetchQuery.

The @ts-expect-error marker ensures TypeScript will flag if select becomes allowed on fetchQuery, maintaining the intended API distinction between legacy and new methods.


229-239: LGTM — Type test validates query accepts select.

This correctly verifies the new query method supports the select option for data transformation, distinguishing it from the legacy fetchQuery. Based on learnings, this aligns with the intended API design.


241-257: LGTM — Type test validates infiniteQuery accepts select.

Correctly verifies that infiniteQuery supports the select option for transforming InfiniteData, aligning with the new API surface documented in learnings.


328-336: LGTM — Correctly uses InfiniteQueryExecuteOptions for typed scenarios.

The type test properly exercises the new InfiniteQueryExecuteOptions interface with explicit TData and TError generics, validating the public API surface.


422-424: LGTM — Tests for new query and infiniteQuery methods with typed options.

Type assertions correctly verify that both new methods return the expected types when used with fully-typed options.

Also applies to: 434-435

packages/query-core/src/__tests__/queryClient.test.tsx (5)

11-11: LGTM — noop is correctly imported from the public API.

This validates that noop is now part of the public API surface as intended by the PR.


529-620: Comprehensive test coverage for query with static staleTime.

Tests correctly cover:

  • Cache hit scenarios (lines 530-544, 546-560)
  • Cache miss with fetch (lines 562-574)
  • initialData behavior (lines 576-590)
  • Manual background revalidation (lines 592-619)

The background revalidation test at line 607-613 correctly demonstrates forcing a refetch with staleTime: 0 while not awaiting the promise.


683-720: LGTM — infiniteQuery with static staleTime tests.

Correctly mirrors the query static staleTime tests for infinite query scenarios, validating cache hits and fresh fetches.


928-1106: Good parity between query and fetchQuery test suites.

The new query method tests properly mirror the existing fetchQuery tests, ensuring behavioral consistency. The tests cover:

  • Strict query key typing
  • Default retry behavior
  • Cache hits
  • Static staleTime with invalidation
  • GC time behavior
  • staleTime-based freshness checks
  • Meta propagation

1287-1380: LGTM — Prefetching tests for infiniteQuery.

Tests correctly validate that infiniteQuery can be used for prefetching by catching errors with noop, including multi-page prefetching and early exit when getNextPageParam returns undefined.

packages/query-core/src/queryClient.ts (1)

343-384: New query method implementation looks correct.

The implementation properly:

  • Defaults retry to false (line 363-365), consistent with fetchQuery
  • Checks staleness before deciding to fetch (line 369-371)
  • Supports select transformation (lines 377-381)

One minor observation: the return at line 383 uses as unknown as TData which is necessary because when select is not provided, TData should equal TQueryData, but TypeScript can't infer this.

packages/vue-query/src/queryClient.ts (2)

258-314: Overload pattern is correct for Vue Query.

The three-signature pattern (plain options, reactive options, implementation) follows the established Vue Query convention used throughout the file (e.g., ensureQueryData, fetchQuery). The implementation correctly delegates to super.query() after unwrapping refs.


316-378: infiniteQuery overloads follow the same correct pattern.

Consistent with the query method and other Vue Query methods in this file. The complex return type conditional is correctly propagated through all overloads.

packages/query-core/src/types.ts (3)

491-509: Well-structured QueryExecuteOptions interface.

The interface correctly:

  • Extends QueryOptions with required queryKey
  • Uses initialPageParam?: never to prevent misuse with infinite queries
  • Includes optional select for data transformation
  • Uses StaleTimeFunction for flexible stale time configuration

The generic parameter order (TQueryFnData, TError, TData, TQueryData, TQueryKey, TPageParam) is consistent with existing types.


561-566: Good rename from FetchInfiniteQueryPages to InfiniteQueryPages.

This makes the type more reusable and removes the "Fetch" prefix since it's now used by both FetchInfiniteQueryOptions and InfiniteQueryExecuteOptions.


568-586: InfiniteQueryExecuteOptions correctly composes base types.

The type properly:

  • Omits initialPageParam from QueryExecuteOptions to re-add it as required via InitialPageParam<TPageParam>
  • Includes InfiniteQueryPages for pagination options
  • Sets appropriate defaults (TData = InfiniteData<TQueryFnData>)

@DogPawHat
Copy link
Contributor Author

@coderabbitai full review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 27, 2025

✅ Actions performed

Full review triggered.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (2)
packages/vue-query/src/queryClient.ts (2)

258-314: Remove the duplicate query overload using MaybeRefDeep.

There are two identical overload declarations for query that both take options: MaybeRefDeep<QueryExecuteOptions<...>>; only one is needed before the implementation. Keeping both can lead to duplicate overload errors in TypeScript, while adding no extra expressiveness.

You can safely drop the middle overload block:

   query<
     TQueryFnData,
     TError = DefaultError,
     TData = TQueryFnData,
     TQueryData = TQueryFnData,
     TQueryKey extends QueryKey = QueryKey,
     TPageParam = never,
   >(
     options: MaybeRefDeep<
       QueryExecuteOptions<
         TQueryFnData,
         TError,
         TData,
         TQueryData,
         TQueryKey,
         TPageParam
       >
     >,
-  ): Promise<TData>
-  query<
-    TQueryFnData,
-    TError = DefaultError,
-    TData = TQueryFnData,
-    TQueryData = TQueryFnData,
-    TQueryKey extends QueryKey = QueryKey,
-    TPageParam = never,
-  >(
-    options: MaybeRefDeep<
-      QueryExecuteOptions<
-        TQueryFnData,
-        TError,
-        TData,
-        TQueryData,
-        TQueryKey,
-        TPageParam
-      >
-    >,
   ): Promise<TData> {
     return super.query(cloneDeepUnref(options))
   }

316-378: Remove the duplicate infiniteQuery overload using MaybeRefDeep.

Similarly, infiniteQuery declares two identical overloads that both accept options: MaybeRefDeep<InfiniteQueryExecuteOptions<...>>; only one is needed in addition to the raw InfiniteQueryExecuteOptions overload and the implementation. This duplication can trigger TypeScript overload errors without adding functionality.

You can remove the extra overload block:

   infiniteQuery<
     TQueryFnData,
     TError = DefaultError,
     TData = InfiniteData<TQueryFnData>,
     TQueryKey extends QueryKey = QueryKey,
     TPageParam = unknown,
   >(
     options: MaybeRefDeep<
       InfiniteQueryExecuteOptions<
         TQueryFnData,
         TError,
         TData,
         TQueryKey,
         TPageParam
       >
     >,
-  ): Promise<
-    Array<TData> extends Array<InfiniteData<TQueryFnData>>
-      ? InfiniteData<TQueryFnData, TPageParam>
-      : TData
-  >
-  infiniteQuery<
-    TQueryFnData,
-    TError = DefaultError,
-    TData = InfiniteData<TQueryFnData>,
-    TQueryKey extends QueryKey = QueryKey,
-    TPageParam = unknown,
-  >(
-    options: MaybeRefDeep<
-      InfiniteQueryExecuteOptions<
-        TQueryFnData,
-        TError,
-        TData,
-        TQueryKey,
-        TPageParam
-      >
-    >,
-  ): Promise<
-    Array<TData> extends Array<InfiniteData<TQueryFnData>>
-      ? InfiniteData<TQueryFnData, TPageParam>
-      : TData
-  > {
+  ): Promise<
+    Array<TData> extends Array<InfiniteData<TQueryFnData>>
+      ? InfiniteData<TQueryFnData, TPageParam>
+      : TData
+  > {
     return super.infiniteQuery(cloneDeepUnref(options))
   }
🧹 Nitpick comments (2)
packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx (1)

79-92: Minor: Comment references wrong hook.

Line 90 mentions "useInfiniteQuery" but this test is for useSuspenseInfiniteQuery. Consider updating the comment for accuracy.

-    // known issue: type of pageParams is unknown when returned from useInfiniteQuery
+    // known issue: type of pageParams is unknown when returned from useSuspenseInfiniteQuery
     expectTypeOf(data).toEqualTypeOf<Array<string>>()
packages/query-core/src/queryClient.ts (1)

428-454: infiniteQuery wiring looks good; consider removing the as any cast.

Using infiniteQueryBehavior(options.pages) and delegating to this.query unifies infinite queries with the new execute surface and reuses the same staleTime/select semantics, which is desirable. The options as any cast, however, bypasses type safety between InfiniteQueryExecuteOptions and QueryExecuteOptions; if possible, consider tightening the generics or extracting a small internal helper so this call site can be fully typed without as any.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aba3260 and bf15113.

📒 Files selected for processing (8)
  • .changeset/famous-owls-battle.md (1 hunks)
  • packages/query-core/src/__tests__/queryClient.test-d.tsx (7 hunks)
  • packages/query-core/src/__tests__/queryClient.test.tsx (9 hunks)
  • packages/query-core/src/queryClient.ts (4 hunks)
  • packages/query-core/src/types.ts (3 hunks)
  • packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx (3 hunks)
  • packages/react-query/src/__tests__/queryOptions.test-d.tsx (2 hunks)
  • packages/vue-query/src/queryClient.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.
📚 Learning: 2025-11-22T09:06:05.219Z
Learnt from: sukvvon
Repo: TanStack/query PR: 9892
File: packages/solid-query-persist-client/src/__tests__/PersistQueryClientProvider.test.tsx:331-335
Timestamp: 2025-11-22T09:06:05.219Z
Learning: In TanStack/query test files, when a queryFn contains side effects (e.g., setting flags for test verification), prefer async/await syntax for clarity; when there are no side effects, prefer the .then() pattern for conciseness.

Applied to files:

  • .changeset/famous-owls-battle.md
  • packages/react-query/src/__tests__/queryOptions.test-d.tsx
  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/query-core/src/__tests__/queryClient.test.tsx
  • packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx
  • packages/vue-query/src/queryClient.ts
  • packages/query-core/src/queryClient.ts
📚 Learning: 2025-11-02T22:52:33.071Z
Learnt from: DogPawHat
Repo: TanStack/query PR: 9835
File: packages/query-core/src/__tests__/queryClient.test-d.tsx:242-256
Timestamp: 2025-11-02T22:52:33.071Z
Learning: In the TanStack Query codebase, the new `query` and `infiniteQuery` methods support the `select` option for data transformation, while the legacy `fetchQuery` and `fetchInfiniteQuery` methods do not support `select` and should reject it at the type level.

Applied to files:

  • .changeset/famous-owls-battle.md
  • packages/react-query/src/__tests__/queryOptions.test-d.tsx
  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/query-core/src/__tests__/queryClient.test.tsx
  • packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx
  • packages/vue-query/src/queryClient.ts
  • packages/query-core/src/queryClient.ts
  • packages/query-core/src/types.ts
📚 Learning: 2025-09-02T17:57:33.184Z
Learnt from: TkDodo
Repo: TanStack/query PR: 9612
File: packages/query-async-storage-persister/src/asyncThrottle.ts:0-0
Timestamp: 2025-09-02T17:57:33.184Z
Learning: When importing from tanstack/query-core in other TanStack Query packages like query-async-storage-persister, a workspace dependency "tanstack/query-core": "workspace:*" needs to be added to the package.json.

Applied to files:

  • .changeset/famous-owls-battle.md
📚 Learning: 2025-08-19T03:18:18.303Z
Learnt from: oscartbeaumont
Repo: TanStack/query PR: 9564
File: packages/solid-query-devtools/src/production.tsx:2-3
Timestamp: 2025-08-19T03:18:18.303Z
Learning: In the solid-query-devtools package, the codebase uses a pattern of type-only default imports combined with typeof for component type annotations (e.g., `import type SolidQueryDevtoolsComp from './devtools'` followed by `typeof SolidQueryDevtoolsComp`). This pattern is consistently used across index.tsx and production.tsx files, and the maintainers prefer consistency over changing this approach.

Applied to files:

  • packages/query-core/src/__tests__/queryClient.test-d.tsx
  • packages/query-core/src/__tests__/queryClient.test.tsx
  • packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx
  • packages/query-core/src/queryClient.ts
🧬 Code graph analysis (3)
packages/query-core/src/__tests__/queryClient.test.tsx (4)
packages/query-core/src/utils.ts (2)
  • noop (93-93)
  • sleep (374-378)
packages/query-core/src/types.ts (1)
  • QueryFunction (96-100)
packages/query-core/src/query.ts (2)
  • promise (198-200)
  • meta (194-196)
packages/query-core/src/mutation.ts (1)
  • meta (124-126)
packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx (5)
packages/query-core/src/queryObserver.ts (1)
  • options (379-385)
packages/react-query/src/index.ts (3)
  • infiniteQueryOptions (26-26)
  • useInfiniteQuery (55-55)
  • useSuspenseInfiniteQuery (12-12)
packages/react-query/src/infiniteQueryOptions.ts (1)
  • infiniteQueryOptions (147-149)
packages/react-query/src/useSuspenseInfiniteQuery.ts (1)
  • useSuspenseInfiniteQuery (18-50)
packages/query-core/src/types.ts (1)
  • InfiniteData (204-207)
packages/vue-query/src/queryClient.ts (4)
packages/query-core/src/types.ts (5)
  • DefaultError (47-51)
  • QueryKey (53-61)
  • QueryExecuteOptions (491-509)
  • InfiniteData (204-207)
  • InfiniteQueryExecuteOptions (568-586)
packages/query-core/src/queryObserver.ts (1)
  • options (379-385)
packages/vue-query/src/types.ts (1)
  • MaybeRefDeep (29-37)
packages/vue-query/src/utils.ts (1)
  • cloneDeepUnref (70-97)
🔇 Additional comments (23)
.changeset/famous-owls-battle.md (1)

1-7: Changeset looks good.

The spelling is correct, and the packages are appropriately marked as minor changes. The description is brief but sufficient for the changeset format.

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

58-66: LGTM!

The test correctly validates that queryOptions works with the new query method, with proper type inference for the return type.


76-95: Comprehensive coverage for select behavior.

These tests properly validate the key design difference: query respects the select option (returning string after transformation), while fetchQuery ignores it (returning the original number). This aligns well with the documented API distinction. Based on learnings, this is the intended behavior.

packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx (3)

53-66: LGTM!

Test correctly validates that useInfiniteQuery with select transforms the data type to Array<string>.


93-117: Tests correctly validate the new infiniteQuery method.

The tests properly verify that:

  1. Basic usage returns InfiniteData<string, number> with correct pageParams inference
  2. With select, the return type is transformed to Array<string>

This aligns with the intended behavior where infiniteQuery supports select. Based on learnings, this is the expected distinction from fetchInfiniteQuery.


130-142: LGTM!

This test correctly validates that fetchInfiniteQuery ignores the select option and returns the full InfiniteData<string, number> type.

packages/query-core/src/__tests__/queryClient.test.tsx (6)

11-11: LGTM!

The noop import is appropriately used throughout the new tests to swallow promise rejections in prefetch-style patterns.


529-620: Comprehensive coverage for query with static staleTime.

The tests properly validate:

  • Cache hits return existing data without calling queryFn
  • Falsy cached data (null) is correctly returned
  • Missing data triggers fetch
  • initialData prevents fetching
  • Manual background revalidation via a second call with staleTime: 0

The manual revalidation test (lines 592-619) is particularly valuable for documenting this use case.


683-720: LGTM!

The infiniteQuery with static staleTime tests mirror the standard query tests appropriately, validating both cache hits and fetching behavior.


928-1106: Tests correctly mirror fetchQuery behavior.

The new query test block comprehensively covers:

  • Strict query key typing
  • No retry by default
  • Cache hit behavior
  • Static staleTime with invalidation
  • Garbage collection timing
  • staleTime-based fetch decisions
  • Meta propagation

This provides confidence that query maintains behavioral parity with fetchQuery.


1287-1380: Good pattern for prefetching with infiniteQuery.

These tests demonstrate using infiniteQuery().catch(noop) as an alternative to prefetchInfiniteQuery. The coverage includes multi-page prefetching and early exit when getNextPageParam returns undefined.


1432-1483: LGTM!

The query used for prefetching tests appropriately demonstrate the .catch(noop) pattern and verify garbage collection behavior.

packages/query-core/src/__tests__/queryClient.test-d.tsx (7)

13-13: LGTM!

The InfiniteQueryExecuteOptions import aligns with the new public API surface introduced in this PR.


161-172: LGTM!

This test correctly validates that fetchQuery rejects the select option at the type level using @ts-expect-error. Based on learnings, this is the intended distinction from the new query method.


175-227: LGTM!

The fetchInfiniteQuery tests correctly validate:

  1. select is rejected with @ts-expect-error
  2. pages option works with proper return typing
  3. getNextPageParam can be passed without pages
  4. pages without getNextPageParam is rejected

229-239: LGTM!

This test correctly validates that the new query method accepts the select option, which is the key API distinction from fetchQuery.


241-293: LGTM!

The infiniteQuery tests comprehensively validate:

  1. select option is allowed (lines 242-257)
  2. pages option works correctly (lines 259-269)
  3. getNextPageParam without pages is allowed (lines 271-280)
  4. pages without getNextPageParam is rejected (lines 282-292)

This matches the expected behavior where infiniteQuery supports select while fetchInfiniteQuery does not.


328-336: LGTM!

The infiniteQueryOptions variable correctly uses the new InfiniteQueryExecuteOptions<TData, TError> type to validate fully-typed usage of the infinite query API.


422-424: LGTM!

The new query and infiniteQuery method calls are properly integrated into the fully-typed usage tests, validating that the return types match expectations.

Also applies to: 434-435

packages/query-core/src/queryClient.ts (2)

16-45: New execute option imports match downstream usage.

Importing InfiniteQueryExecuteOptions and QueryExecuteOptions here lines up with the new query and infiniteQuery methods below and keeps the execute surface types clearly separate from the legacy fetch option types.


343-384: query correctly implements the cache-aware execute surface with select.

This mirrors fetchQuery’s retry/staleTime behavior while adding an optional post-fetch select transform against the cached/fetched queryData, using resolveStaleTime so both numeric and function-based (including 'static') stale times are respected without unnecessary refetches. This matches the intended contract where the new imperative query API supports select while fetchQuery remains simpler. Based on learnings, this is the right place to expose select.

packages/vue-query/src/queryClient.ts (1)

9-37: Vue QueryClient imports correctly mirror the core execute types.

Bringing in InfiniteQueryExecuteOptions and QueryExecuteOptions ensures the Vue wrapper exposes the same execute signatures as the core QueryClient, while still relying on local MaybeRefDeep for ref-unwrapping.

packages/query-core/src/types.ts (1)

491-509: Execute option types cleanly separate the execute and fetch surfaces.

QueryExecuteOptions extends QueryOptions with a required queryKey, a select transform, and a staleTime expressed as StaleTimeFunction, while explicitly disallowing initialPageParam. InfiniteQueryExecuteOptions then layers infinite-specific concerns (InitialPageParam and the shared InfiniteQueryPages helper) on top, and reusing InfiniteQueryPages inside FetchInfiniteQueryOptions keeps execute and fetch infinite options structurally aligned without introducing select on the legacy fetch surface. This matches the desired contract that only query/infiniteQuery support select, while fetchQuery/fetchInfiniteQuery continue to reject it at the type level. Based on learnings, this design looks correct.

Also applies to: 561-587, 588-606

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants