Skip to content

Conversation

@VedantMadane
Copy link

@VedantMadane VedantMadane commented Jan 15, 2026

Fixes #7892

The return type of queryOptions in vue-query was using types wrapped in MaybeRef which prevented TypeScript from seeing properties like queryFn, staleTime, placeholderData, etc directly on the returned object.

Solution: Created unwrapped types (DefinedInitialDataOptions and UndefinedInitialDataOptions) specifically for queryOptions, matching react-query's approach. These use QueryObserverOptions directly without MaybeRef.

Changes:

  • packages/vue-query/src/queryOptions.ts - Added unwrapped option types
  • packages/vue-query/src/tests/queryOptions.test-d.ts - Added test for queryFn accessibility

Testing: 17 type tests pass including new test verifying queryFn and staleTime are accessible on returned options object.

Summary by CodeRabbit

  • Tests

    • Added type-level assertions to ensure query options expose queryFn, staleTime, and queryKey with correct typings.
  • Refactor

    • Tightened query options types to make initial-data handling and queryFn typings more explicit and reliable.
  • Chores

    • Added a changeset to publish a patch for the type updates.

@changeset-bot
Copy link

changeset-bot bot commented Jan 15, 2026

🦋 Changeset detected

Latest commit: 449ab13

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

This PR includes changesets to release 2 packages
Name Type
@tanstack/vue-query Patch
@tanstack/vue-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 Jan 15, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR updates vue-query TypeScript typings: it adds DefinedInitialDataOptions and UndefinedInitialDataOptions, updates queryOptions overloads to expose queryFn and related fields on returned types, adds a type-only test asserting those types, and includes a changeset noting the fix.

Changes

Cohort / File(s) Summary
Type definitions
packages/vue-query/src/queryOptions.ts
Add DefinedInitialDataOptions and UndefinedInitialDataOptions aliases; import QueryFunction and DeepUnwrapRef; update queryOptions overloads to accept/return the new option types and include queryKey: DataTag<...>; implementation unchanged.
Type tests
packages/vue-query/src/__tests__/queryOptions.test-d.ts
Add a TypeScript-only test asserting the returned queryOptions exposes queryFn, staleTime, and queryKey with expected types.
Changeset / release note
.changeset/fix-query-options-types-fix.md
Add patch changeset documenting the fix that exposes queryFn and additional properties on the queryOptions return type.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • DamianOsipiuk
  • TkDodo

Poem

🐇
I hopped through types by lantern light,
Found the missing fields tucked out of sight.
With aliases neat and signatures true,
QueryFn returned—hooray! anew. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main change: exposing queryFn and other properties on the queryOptions return type in vue-query.
Description check ✅ Passed The description covers the main changes, references the linked issue (#7892), explains the solution, lists modified files, and confirms testing was performed; however, the checklist items are not marked.
Linked Issues check ✅ Passed The PR directly addresses all coding requirements from issue #7892: exposing queryFn and other properties on queryOptions return type by introducing unwrapped option types and removing MaybeRef wrapping to align with react-query.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the queryOptions typing issue: new unwrapped option types, updated function overloads, a type test, and a changeset entry. No unrelated modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉


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.

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

Caution

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

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

56-80: Add UnusedSkipTokenOptions overload to match react-query's type safety for skipToken scenarios.

The queryOptions function is missing a critical overload. React-query's implementation includes a UnusedSkipTokenOptions overload (between DefinedInitialDataOptions and UndefinedInitialDataOptions) that prevents skipToken from being assigned to the queryFn property in conditional scenarios.

Vue-query's tests already use this pattern (e.g., queryFn: Math.random() > 0.5 ? skipToken : () => Promise.resolve(5)), but without the intermediate overload, TypeScript cannot properly narrow the type for skipToken cases. Add the missing overload definition and overload signature to provide consistent type safety across all framework implementations:

export type UnusedSkipTokenOptions<
  TQueryFnData = unknown,
  TError = DefaultError,
  TData = TQueryFnData,
  TQueryKey extends QueryKey = QueryKey,
> = Omit<
  QueryObserverOptions<TQueryFnData, TError, TData, TQueryFnData, DeepUnwrapRef<TQueryKey>>,
  'queryFn'
> & ShallowOption & {
  queryFn?: Exclude<
    QueryObserverOptions<TQueryFnData, TError, TData, TQueryFnData, DeepUnwrapRef<TQueryKey>>['queryFn'],
    SkipToken | undefined
  >
}

export function queryOptions<...>(
  options: UnusedSkipTokenOptions<...>,
): UnusedSkipTokenOptions<...> & {
  queryKey: DataTag<TQueryKey, TQueryFnData, TError>
}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bf7f47e and cc06f3c.

📒 Files selected for processing (2)
  • packages/vue-query/src/__tests__/queryOptions.test-d.ts
  • packages/vue-query/src/queryOptions.ts
🧰 Additional context used
🧠 Learnings (4)
📓 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.
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.
📚 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/vue-query/src/__tests__/queryOptions.test-d.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/vue-query/src/__tests__/queryOptions.test-d.ts
  • packages/vue-query/src/queryOptions.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/vue-query/src/queryOptions.ts
🧬 Code graph analysis (1)
packages/vue-query/src/__tests__/queryOptions.test-d.ts (1)
packages/vue-query/src/queryOptions.ts (1)
  • queryOptions (78-80)
🔇 Additional comments (3)
packages/vue-query/src/__tests__/queryOptions.test-d.ts (1)

9-22: LGTM! Well-structured type test for issue #7892.

The test correctly verifies that:

  • queryFn and staleTime are accessible with proper types including undefined (since they're optional)
  • queryKey uses toMatchTypeOf appropriately since the actual type is DataTag<...> which extends readonly unknown[]
packages/vue-query/src/queryOptions.ts (2)

11-31: LGTM! Clean type definition that directly addresses the core issue.

Using QueryObserverOptions directly (rather than wrapped in MaybeRef) ensures that properties like queryFn, staleTime, etc. are accessible on the returned options object. The JSDoc comment clearly documents the design intent.


33-54: LGTM! Correct distinction from DefinedInitialDataOptions.

The initialData field properly allows:

  • Omission (optional with ?)
  • Explicit undefined
  • A function that may return undefined (InitialDataFunction)
  • A direct non-undefined value

This ensures the overload resolution correctly routes to DefinedInitialDataOptions when initialData is guaranteed to be defined.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@nx-cloud
Copy link

nx-cloud bot commented Jan 26, 2026

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit c790f78

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ❌ Failed 1m 18s View ↗
nx run-many --target=build --exclude=examples/*... ❌ Failed 15s View ↗

☁️ Nx Cloud last updated this comment at 2026-01-26 14:07:40 UTC

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

🤖 Fix all issues with AI agents
In `@packages/vue-query/src/__tests__/queryOptions.test-d.ts`:
- Around line 9-22: Test uses the inline readonly-array syntax that the
project's ESLint config disallows; update the assertion for queryKey to use the
generic readonly array type instead. Specifically, in the test around
expectTypeOf(options.queryKey).toMatchTypeOf<...>(), replace the current
readonly unknown[] type with ReadonlyArray<unknown> so the assertion uses the
ReadonlyArray generic form (locate the expectTypeOf call referencing
options.queryKey in this test file).

…eturn type

The return type of queryOptions was using types wrapped in MaybeRef, which
prevented TypeScript from seeing properties like queryFn directly on the
returned object.

This creates new unwrapped types (DefinedInitialDataOptions and
UndefinedInitialDataOptions) specifically for queryOptions return types,
matching the approach used in react-query.

Fixes TanStack#7892

Signed-off-by: Vedant Madane <6527493+VedantMadane@users.noreply.github.com>
Expose queryFn and other properties on queryOptions return type.
- Replace QueryObserverOptions with intersection of existing types
- Maintains compatibility with useQuery overloads
- Uses UndefinedInitialQueryOptions & DefinedInitialQueryOptions as base
- Explicitly exposes queryKey and queryFn properties
- Update test to use toMatchTypeOf for intersection types
- Change readonly unknown[] to ReadonlyArray<unknown>
- Complies with project's ESLint config that disallows inline readonly syntax
@VedantMadane VedantMadane force-pushed the fix/vue-query-options-types branch from c790f78 to 449ab13 Compare February 10, 2026 10:00
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.

[vue-query] Type error: queryOptions return type only contains the queryKey and initialData properties

1 participant