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-checking assertions for query options to verify correct type exposure.
  • Refactor

    • Updated query options type definitions for improved type safety and consistency with initial data handling.

✏️ 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 <[email protected]>
@changeset-bot
Copy link

changeset-bot bot commented Jan 15, 2026

⚠️ No Changeset found

Latest commit: cc06f3c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

This PR fixes a TypeScript type issue in vue-query's queryOptions function where accessing properties like queryFn and staleTime on the returned options object caused type errors. It introduces new option types (DefinedInitialDataOptions and UndefinedInitialDataOptions) that properly preserve the full options structure in the return type, with type assertions added to verify correctness.

Changes

Cohort / File(s) Summary
Type Definitions
packages/vue-query/src/queryOptions.ts
Introduces DefinedInitialDataOptions and UndefinedInitialDataOptions types replacing previous option types. Updates queryOptions function overloads to accept and return these new types augmented with queryKey (DataTag). Preserves pass-through implementation behavior while fixing return type to expose all options properties.
Type Assertions
packages/vue-query/src/__tests__/queryOptions.test-d.ts
Adds test case to verify returned options object properly exposes queryFn, staleTime, and queryKey with correct types.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

package: vue-query

Suggested reviewers

  • DamianOsipiuk
  • TkDodo

Poem

🐰 A rabbit's ode to types made right:
Where queryFn hid from TypeScript's sight,
New types bring structure, properties in view,
No more errors on autocomplete's queue!
The options shine bright, complete and true. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing the queryOptions return type to expose queryFn and other properties, which directly addresses issue #7892.
Description check ✅ Passed The PR description includes a clear explanation of the issue, the solution approach, files changed, and testing results, though it lacks a formal checklist completion.
Linked Issues check ✅ Passed The changes fully address issue #7892 by introducing unwrapped option types (DefinedInitialDataOptions and UndefinedInitialDataOptions) that expose queryFn and other properties directly on the returned object, matching react-query's approach.
Out of Scope Changes check ✅ Passed All changes are directly related to the linked issue #7892: modifications to queryOptions.ts types and a test case verifying queryFn accessibility are both in scope.
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


📜 Recent 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.


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.

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