diff --git a/.changeset/fix-vue-query-options-type.md b/.changeset/fix-vue-query-options-type.md new file mode 100644 index 0000000000..13e821520b --- /dev/null +++ b/.changeset/fix-vue-query-options-type.md @@ -0,0 +1,11 @@ +--- +'@tanstack/vue-query': patch +--- + +fix(vue-query): fix queryOptions return type to expose all properties + +The `queryOptions` return type now correctly exposes all query option +properties (like `queryFn`, `staleTime`, etc.) for direct access, not +just `queryKey` and `initialData`. This is achieved by excluding the +`Ref` and `ComputedRef` branches from the `MaybeRef` union in the return +type, since `queryOptions` always returns a plain object. diff --git a/packages/vue-query/src/__tests__/queryOptions.test-d.ts b/packages/vue-query/src/__tests__/queryOptions.test-d.ts index 65d49d945f..a1edba838e 100644 --- a/packages/vue-query/src/__tests__/queryOptions.test-d.ts +++ b/packages/vue-query/src/__tests__/queryOptions.test-d.ts @@ -212,4 +212,14 @@ describe('queryOptions', () => { expectTypeOf(data).toEqualTypeOf() }) + + it('should allow accessing queryFn and other properties on the returned options object', () => { + const options = queryOptions({ + queryKey: ['groups'], + queryFn: () => Promise.resolve([]), + }) + + expectTypeOf(options.queryFn).not.toBeUndefined() + expectTypeOf(options.queryKey).not.toBeUndefined() + }) }) diff --git a/packages/vue-query/src/queryOptions.ts b/packages/vue-query/src/queryOptions.ts index 4681080f8c..ba053dd3cd 100644 --- a/packages/vue-query/src/queryOptions.ts +++ b/packages/vue-query/src/queryOptions.ts @@ -3,6 +3,14 @@ import type { DefinedInitialQueryOptions, UndefinedInitialQueryOptions, } from './useQuery' +import type { ComputedRef, Ref } from 'vue-demi' + +// Removes Ref and ComputedRef branches from a MaybeRef union type, +// leaving only the plain object type so all properties are directly +// accessible via dot notation. +// Fixes #7892: queryOptions return type only contains queryKey and +// initialData properties due to MaybeRef union narrowing. +type PlainQueryOptions = Exclude | ComputedRef> export function queryOptions< TQueryFnData = unknown, @@ -11,7 +19,9 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: DefinedInitialQueryOptions, -): DefinedInitialQueryOptions & { +): PlainQueryOptions< + DefinedInitialQueryOptions +> & { queryKey: DataTag } @@ -22,7 +32,9 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: UndefinedInitialQueryOptions, -): UndefinedInitialQueryOptions & { +): PlainQueryOptions< + UndefinedInitialQueryOptions +> & { queryKey: DataTag } diff --git a/packages/vue-query/src/useQueries.ts b/packages/vue-query/src/useQueries.ts index f290976a14..385b6720ff 100644 --- a/packages/vue-query/src/useQueries.ts +++ b/packages/vue-query/src/useQueries.ts @@ -14,6 +14,7 @@ import { useQueryClient } from './useQueryClient' import { cloneDeepUnref } from './utils' import type { Ref } from 'vue-demi' import type { + DataTag, DefaultError, DefinedQueryObserverResult, QueriesObserverOptions, @@ -45,6 +46,10 @@ type GetUseQueryOptionsForUseQueries = // Part 1: if UseQueryOptions are already being sent through, then just return T T extends UseQueryOptions ? DeepUnwrapRef + : // Part 1b: handle plain query options returned by queryOptions() + // (ExtractPlainType removes MaybeRef branches, so they need DeepUnwrapRef too) + T extends { queryKey: DataTag } + ? DeepUnwrapRef : // Part 2: responsible for applying explicit type parameter to function arguments, if object { queryFnData: TQueryFnData, error: TError, data: TData } T extends { queryFnData: infer TQueryFnData @@ -123,6 +128,19 @@ type GetUseQueryResult = undefined extends TData ? TQueryFnData : TData, unknown extends TError ? DefaultError : TError > + : // Part 1b: handle plain query options from queryOptions() + T extends { queryKey: DataTag } + ? T extends { select?: (data: any) => infer TData } + ? GetDefinedOrUndefinedQueryResult< + T, + unknown extends TData ? TQueryFnData : TData, + unknown extends TError ? DefaultError : TError + > + : GetDefinedOrUndefinedQueryResult< + T, + TQueryFnData, + unknown extends TError ? DefaultError : TError + > : // Part 2: responsible for mapping explicit type parameter to function result, if object T extends { queryFnData: any; error?: infer TError; data: infer TData } ? GetDefinedOrUndefinedQueryResult