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 types.
  • Refactor

    • Clarified and tightened query options types to make initial-data handling and queryFn typing more explicit and safer.
  • Chores

    • Added a changeset to publish a patch addressing the type fixes.

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

…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>
@changeset-bot
Copy link

changeset-bot bot commented Jan 15, 2026

🦋 Changeset detected

Latest commit: c790f78

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

📝 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 use the new option types and return types augmented with queryKey: DataTag<...>; implementation signature unchanged.
Type tests
packages/vue-query/src/__tests__/queryOptions.test-d.ts
Add TypeScript-only test asserting returned queryOptions exposes queryFn, staleTime, and queryKey with expected types.
Changeset / release note
.changeset/fix-query-options-types-fix.md
Add patch changeset describing exposure of queryFn and additional properties on queryOptions return type.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • TkDodo
  • DamianOsipiuk

Poem

🐇
I hopped through types with moonlit cheer,
Uncovered queryFn now bright and clear.
Aliases stitched the hidden seam,
Options now awake—no longer dream. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: exposing queryFn and other properties on the queryOptions return type in vue-query, which directly addresses the issue being fixed.
Description check ✅ Passed The PR description comprehensively covers the changes, references the linked issue (#7892), explains the motivation and solution, lists modified files, and confirms testing results.
Linked Issues check ✅ Passed The PR fully addresses all objectives from issue #7892: creates unwrapped option types to expose queryFn and other properties, maintains runtime compatibility, and aligns vue-query with react-query by removing MaybeRef wrapping.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the queryOptions return type issue. The changeset file, type definitions, and type tests are all in-scope for resolving the linked issue.
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

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

- 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
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).

- Change readonly unknown[] to ReadonlyArray<unknown>
- Complies with project's ESLint config that disallows inline readonly syntax
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