diff --git a/.changeset/fix-query-options-declaration-emit.md b/.changeset/fix-query-options-declaration-emit.md new file mode 100644 index 00000000000..fc700263aa9 --- /dev/null +++ b/.changeset/fix-query-options-declaration-emit.md @@ -0,0 +1,11 @@ +--- +'@tanstack/query-core': patch +'@tanstack/angular-query-experimental': patch +'@tanstack/preact-query': patch +'@tanstack/react-query': patch +'@tanstack/solid-query': patch +'@tanstack/svelte-query': patch +'@tanstack/vue-query': patch +--- + +Fix `queryOptions` and `infiniteQueryOptions` return types so exported inferred options can be emitted in declaration files without leaking internal data tag symbols. diff --git a/integrations/vue-declaration-emit/consumer/query-options.ts b/integrations/vue-declaration-emit/consumer/query-options.ts new file mode 100644 index 00000000000..8bdcbeef9fd --- /dev/null +++ b/integrations/vue-declaration-emit/consumer/query-options.ts @@ -0,0 +1,9 @@ +import { + definedInitialDataOptions, + undefinedInitialDataOptions, +} from '../dist/query-options.js' + +export const options = { + definedInitialDataOptions, + undefinedInitialDataOptions, +} diff --git a/integrations/vue-declaration-emit/package.json b/integrations/vue-declaration-emit/package.json new file mode 100644 index 00000000000..a7d3455be6e --- /dev/null +++ b/integrations/vue-declaration-emit/package.json @@ -0,0 +1,26 @@ +{ + "name": "vue-declaration-emit", + "private": true, + "type": "module", + "scripts": { + "test:types": "pnpm run test:types:ts6 && pnpm run test:types:ts7", + "test:types:ts6": "node ../../node_modules/typescript/lib/tsc.js --pretty false --project tsconfig.emit.json && node ../../node_modules/typescript/lib/tsc.js --pretty false --project tsconfig.consume.json", + "test:types:ts7": "node ../../node_modules/typescript70/lib/tsc.js --pretty false --project tsconfig.emit.json && node ../../node_modules/typescript70/lib/tsc.js --pretty false --project tsconfig.consume.json" + }, + "dependencies": { + "@tanstack/vue-query": "workspace:*", + "vue": "^3.4.27" + }, + "devDependencies": { + "typescript": "5.8.3" + }, + "nx": { + "targets": { + "test:types": { + "dependsOn": [ + "^build" + ] + } + } + } +} diff --git a/integrations/vue-declaration-emit/src/query-options.ts b/integrations/vue-declaration-emit/src/query-options.ts new file mode 100644 index 00000000000..4fcfcd16ed2 --- /dev/null +++ b/integrations/vue-declaration-emit/src/query-options.ts @@ -0,0 +1,14 @@ +import { queryOptions } from '@tanstack/vue-query' + +/** @public */ +export const undefinedInitialDataOptions = queryOptions({ + queryKey: ['undefined-initial-data'], + queryFn: async () => ({ value: 'data' }), +}) + +/** @public */ +export const definedInitialDataOptions = queryOptions({ + queryKey: ['defined-initial-data'], + queryFn: async () => ({ value: 'data' }), + initialData: { value: 'initial data' }, +}) diff --git a/integrations/vue-declaration-emit/tsconfig.consume.json b/integrations/vue-declaration-emit/tsconfig.consume.json new file mode 100644 index 00000000000..6cba091b2c7 --- /dev/null +++ b/integrations/vue-declaration-emit/tsconfig.consume.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "noEmit": true, + "skipLibCheck": false, + "strict": true + }, + "include": ["./consumer"] +} diff --git a/integrations/vue-declaration-emit/tsconfig.emit.json b/integrations/vue-declaration-emit/tsconfig.emit.json new file mode 100644 index 00000000000..7206033e8ed --- /dev/null +++ b/integrations/vue-declaration-emit/tsconfig.emit.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "declaration": true, + "emitDeclarationOnly": true, + "strict": true, + "rootDir": "./src", + "outDir": "./dist" + }, + "include": ["./src"] +} diff --git a/packages/angular-query-experimental/src/__tests__/infinite-query-options.test-d.ts b/packages/angular-query-experimental/src/__tests__/infinite-query-options.test-d.ts index 9c11ce039e6..e9f41ed3b60 100644 --- a/packages/angular-query-experimental/src/__tests__/infinite-query-options.test-d.ts +++ b/packages/angular-query-experimental/src/__tests__/infinite-query-options.test-d.ts @@ -10,6 +10,15 @@ import type { InitialDataFunction, } from '@tanstack/query-core' +// Regression test for exported infiniteQueryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedInfiniteQueryOptions = infiniteQueryOptions({ + queryKey: ['invalid'], + getNextPageParam: () => 1, + initialPageParam: 1, +}) + describe('infiniteQueryOptions', () => { it('should not allow excess properties', () => { const key = queryKey() diff --git a/packages/angular-query-experimental/src/__tests__/query-options.test-d.ts b/packages/angular-query-experimental/src/__tests__/query-options.test-d.ts index c6a0e6d8fda..c4462afaa34 100644 --- a/packages/angular-query-experimental/src/__tests__/query-options.test-d.ts +++ b/packages/angular-query-experimental/src/__tests__/query-options.test-d.ts @@ -9,6 +9,13 @@ import { } from '..' import type { Signal } from '@angular/core' +// Regression test for exported queryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedQueryOptions = queryOptions({ + queryKey: ['invalid'], +}) + describe('queryOptions', () => { it('should not allow excess properties', () => { expectTypeOf(queryOptions).parameter(0).not.toHaveProperty('stallTime') diff --git a/packages/angular-query-experimental/src/infinite-query-options.ts b/packages/angular-query-experimental/src/infinite-query-options.ts index 0bed440730b..b09b194c6b9 100644 --- a/packages/angular-query-experimental/src/infinite-query-options.ts +++ b/packages/angular-query-experimental/src/infinite-query-options.ts @@ -1,11 +1,11 @@ import type { - DataTag, DefaultError, InfiniteData, InitialDataFunction, NonUndefinedGuard, OmitKeyof, QueryKey, + QueryKeyWithDataTag, SkipToken, } from '@tanstack/query-core' import type { CreateInfiniteQueryOptions } from './types' @@ -105,9 +105,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> /** * Allows sharing and re-using infinite query options in a type-safe way. @@ -136,9 +135,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> /** * Allows sharing and re-using infinite query options in a type-safe way. @@ -167,9 +165,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> /** * Allows sharing and re-using infinite query options in a type-safe way. diff --git a/packages/angular-query-experimental/src/query-options.ts b/packages/angular-query-experimental/src/query-options.ts index 14a50074b06..4f6897618ec 100644 --- a/packages/angular-query-experimental/src/query-options.ts +++ b/packages/angular-query-experimental/src/query-options.ts @@ -1,11 +1,11 @@ import type { - DataTag, DefaultError, InitialDataFunction, NonUndefinedGuard, OmitKeyof, QueryFunction, QueryKey, + QueryKeyWithDataTag, SkipToken, } from '@tanstack/query-core' import type { CreateQueryOptions } from './types' @@ -80,9 +80,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: DefinedInitialDataOptions, -): DefinedInitialDataOptions & { - queryKey: DataTag -} +): DefinedInitialDataOptions & + QueryKeyWithDataTag /** * Allows sharing and re-using query options in a type-safe way. @@ -112,9 +111,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: UnusedSkipTokenOptions, -): UnusedSkipTokenOptions & { - queryKey: DataTag -} +): UnusedSkipTokenOptions & + QueryKeyWithDataTag /** * Allows sharing and re-using query options in a type-safe way. @@ -144,9 +142,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: UndefinedInitialDataOptions, -): UndefinedInitialDataOptions & { - queryKey: DataTag -} +): UndefinedInitialDataOptions & + QueryKeyWithDataTag /** * Allows sharing and re-using query options in a type-safe way. diff --git a/packages/preact-query/src/__tests__/infiniteQueryOptions.test-d.tsx b/packages/preact-query/src/__tests__/infiniteQueryOptions.test-d.tsx index 047d877ac3f..563e7a69114 100644 --- a/packages/preact-query/src/__tests__/infiniteQueryOptions.test-d.tsx +++ b/packages/preact-query/src/__tests__/infiniteQueryOptions.test-d.tsx @@ -12,6 +12,15 @@ import { useInfiniteQuery } from '../useInfiniteQuery' import { useQuery } from '../useQuery' import { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery' +// Regression test for exported infiniteQueryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedInfiniteQueryOptions = infiniteQueryOptions({ + queryKey: ['invalid'], + getNextPageParam: () => 1, + initialPageParam: 1, +}) + describe('infiniteQueryOptions', () => { it('should not allow excess properties', () => { assertType( diff --git a/packages/preact-query/src/__tests__/queryOptions.test-d.tsx b/packages/preact-query/src/__tests__/queryOptions.test-d.tsx index 4fd5c37e8fa..9b0c5183161 100644 --- a/packages/preact-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/preact-query/src/__tests__/queryOptions.test-d.tsx @@ -18,6 +18,13 @@ import { useQueries } from '../useQueries' import { useQuery } from '../useQuery' import { useSuspenseQuery } from '../useSuspenseQuery' +// Regression test for exported queryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedQueryOptions = queryOptions({ + queryKey: ['invalid'], +}) + describe('queryOptions', () => { it('should not allow excess properties', () => { assertType( diff --git a/packages/preact-query/src/infiniteQueryOptions.ts b/packages/preact-query/src/infiniteQueryOptions.ts index 6e1e0be3bc7..660f00b1de3 100644 --- a/packages/preact-query/src/infiniteQueryOptions.ts +++ b/packages/preact-query/src/infiniteQueryOptions.ts @@ -1,11 +1,11 @@ import type { - DataTag, DefaultError, InfiniteData, InitialDataFunction, NonUndefinedGuard, OmitKeyof, QueryKey, + QueryKeyWithDataTag, SkipToken, } from '@tanstack/query-core' @@ -93,9 +93,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> export function infiniteQueryOptions< TQueryFnData, @@ -117,9 +116,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> export function infiniteQueryOptions< TQueryFnData, @@ -141,9 +139,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> export function infiniteQueryOptions(options: unknown) { return options diff --git a/packages/preact-query/src/queryOptions.ts b/packages/preact-query/src/queryOptions.ts index bdf19e97584..3b61de09126 100644 --- a/packages/preact-query/src/queryOptions.ts +++ b/packages/preact-query/src/queryOptions.ts @@ -1,11 +1,11 @@ import type { - DataTag, DefaultError, InitialDataFunction, NonUndefinedGuard, OmitKeyof, QueryFunction, QueryKey, + QueryKeyWithDataTag, SkipToken, } from '@tanstack/query-core' @@ -57,9 +57,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: DefinedInitialDataOptions, -): DefinedInitialDataOptions & { - queryKey: DataTag -} +): DefinedInitialDataOptions & + QueryKeyWithDataTag export function queryOptions< TQueryFnData = unknown, @@ -68,9 +67,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: UnusedSkipTokenOptions, -): UnusedSkipTokenOptions & { - queryKey: DataTag -} +): UnusedSkipTokenOptions & + QueryKeyWithDataTag export function queryOptions< TQueryFnData = unknown, @@ -79,9 +77,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: UndefinedInitialDataOptions, -): UndefinedInitialDataOptions & { - queryKey: DataTag -} +): UndefinedInitialDataOptions & + QueryKeyWithDataTag export function queryOptions(options: unknown) { return options diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index b71039d332b..a413376d46d 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -79,6 +79,14 @@ export type DataTag< [dataTagErrorSymbol]: TError } +export type QueryKeyWithDataTag< + TQueryKey extends QueryKey = QueryKey, + TQueryFnData = unknown, + TError = DefaultError, +> = { + queryKey: DataTag +} + export type InferDataFromTag = TTaggedQueryKey extends DataTag ? TaggedValue diff --git a/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx b/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx index 4f72db57d4c..ae160129ca1 100644 --- a/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx @@ -11,6 +11,15 @@ import type { InitialDataFunction, } from '@tanstack/query-core' +// Regression test for exported infiniteQueryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedInfiniteQueryOptions = infiniteQueryOptions({ + queryKey: ['invalid'], + getNextPageParam: () => 1, + initialPageParam: 1, +}) + describe('infiniteQueryOptions', () => { it('should not allow excess properties', () => { assertType( diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index dfeedcff64b..a818a00e457 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -18,6 +18,13 @@ import type { QueryPersister, } from '@tanstack/query-core' +// Regression test for exported queryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedQueryOptions = queryOptions({ + queryKey: ['invalid'], +}) + describe('queryOptions', () => { it('should not allow excess properties', () => { assertType( diff --git a/packages/react-query/src/infiniteQueryOptions.ts b/packages/react-query/src/infiniteQueryOptions.ts index 5e8c371a59f..bccc9699da3 100644 --- a/packages/react-query/src/infiniteQueryOptions.ts +++ b/packages/react-query/src/infiniteQueryOptions.ts @@ -1,11 +1,11 @@ import type { - DataTag, DefaultError, InfiniteData, InitialDataFunction, NonUndefinedGuard, OmitKeyof, QueryKey, + QueryKeyWithDataTag, SkipToken, } from '@tanstack/query-core' import type { UseInfiniteQueryOptions } from './types' @@ -92,9 +92,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> export function infiniteQueryOptions< TQueryFnData, @@ -116,9 +115,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> export function infiniteQueryOptions< TQueryFnData, @@ -140,9 +138,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> export function infiniteQueryOptions(options: unknown) { return options diff --git a/packages/react-query/src/queryOptions.ts b/packages/react-query/src/queryOptions.ts index 644ac26788b..852a6c3b61c 100644 --- a/packages/react-query/src/queryOptions.ts +++ b/packages/react-query/src/queryOptions.ts @@ -1,11 +1,11 @@ import type { - DataTag, DefaultError, InitialDataFunction, NonUndefinedGuard, OmitKeyof, QueryFunction, QueryKey, + QueryKeyWithDataTag, SkipToken, } from '@tanstack/query-core' import type { UseQueryOptions } from './types' @@ -56,9 +56,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: DefinedInitialDataOptions, -): DefinedInitialDataOptions & { - queryKey: DataTag -} +): DefinedInitialDataOptions & + QueryKeyWithDataTag export function queryOptions< TQueryFnData = unknown, @@ -67,9 +66,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: UnusedSkipTokenOptions, -): UnusedSkipTokenOptions & { - queryKey: DataTag -} +): UnusedSkipTokenOptions & + QueryKeyWithDataTag export function queryOptions< TQueryFnData = unknown, @@ -78,9 +76,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: UndefinedInitialDataOptions, -): UndefinedInitialDataOptions & { - queryKey: DataTag -} +): UndefinedInitialDataOptions & + QueryKeyWithDataTag export function queryOptions(options: unknown) { return options diff --git a/packages/solid-query/src/__tests__/infiniteQueryOptions.test-d.tsx b/packages/solid-query/src/__tests__/infiniteQueryOptions.test-d.tsx index 39978d9658f..be3a19cb97d 100644 --- a/packages/solid-query/src/__tests__/infiniteQueryOptions.test-d.tsx +++ b/packages/solid-query/src/__tests__/infiniteQueryOptions.test-d.tsx @@ -9,6 +9,15 @@ import type { UndefinedInitialDataInfiniteOptions, } from '../infiniteQueryOptions' +// Regression test for exported infiniteQueryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedInfiniteQueryOptions = infiniteQueryOptions({ + queryKey: ['invalid'], + getNextPageParam: () => 1, + initialPageParam: 1, +}) + describe('infiniteQueryOptions', () => { it('should work when passed to infiniteQuery', async () => { const options = infiniteQueryOptions({ diff --git a/packages/solid-query/src/__tests__/queryOptions.test-d.tsx b/packages/solid-query/src/__tests__/queryOptions.test-d.tsx index 88f811bb77b..05672ba10cb 100644 --- a/packages/solid-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/solid-query/src/__tests__/queryOptions.test-d.tsx @@ -9,6 +9,13 @@ import { queryKey } from '@tanstack/query-test-utils' import { useQuery } from '../useQuery' import { queryOptions } from '../queryOptions' +// Regression test for exported queryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedQueryOptions = queryOptions({ + queryKey: ['invalid'], +}) + describe('queryOptions', () => { it('should not allow excess properties', () => { assertType( diff --git a/packages/solid-query/src/infiniteQueryOptions.ts b/packages/solid-query/src/infiniteQueryOptions.ts index 6f4885d999f..1648882d2f3 100644 --- a/packages/solid-query/src/infiniteQueryOptions.ts +++ b/packages/solid-query/src/infiniteQueryOptions.ts @@ -1,9 +1,9 @@ import type { - DataTag, DefaultError, InfiniteData, NonUndefinedGuard, QueryKey, + QueryKeyWithDataTag, } from '@tanstack/query-core' import type { InfiniteQueryOptions } from './types' import type { Accessor } from 'solid-js' @@ -58,9 +58,8 @@ export function infiniteQueryOptions< TQueryKey, TPageParam > -> & { - queryKey: DataTag> -} +> & + QueryKeyWithDataTag, TError> export function infiniteQueryOptions< TQueryFnData, TError = DefaultError, @@ -85,9 +84,8 @@ export function infiniteQueryOptions< TQueryKey, TPageParam > -> & { - queryKey: DataTag> -} +> & + QueryKeyWithDataTag, TError> export function infiniteQueryOptions(options: unknown) { return options diff --git a/packages/solid-query/src/queryOptions.ts b/packages/solid-query/src/queryOptions.ts index fea9db1e1f3..55e16871eab 100644 --- a/packages/solid-query/src/queryOptions.ts +++ b/packages/solid-query/src/queryOptions.ts @@ -1,4 +1,8 @@ -import type { DataTag, DefaultError, QueryKey } from '@tanstack/query-core' +import type { + DefaultError, + QueryKey, + QueryKeyWithDataTag, +} from '@tanstack/query-core' import type { QueryOptions } from './types' import type { Accessor } from 'solid-js' @@ -35,9 +39,8 @@ export function queryOptions< >, ): ReturnType< UndefinedInitialDataOptions -> & { - queryKey: DataTag -} +> & + QueryKeyWithDataTag export function queryOptions< TQueryFnData = unknown, @@ -50,9 +53,8 @@ export function queryOptions< >, ): ReturnType< DefinedInitialDataOptions -> & { - queryKey: DataTag -} +> & + QueryKeyWithDataTag export function queryOptions(options: unknown) { return options diff --git a/packages/svelte-query/src/queryOptions.ts b/packages/svelte-query/src/queryOptions.ts index e1a44be6317..1511ba85a63 100644 --- a/packages/svelte-query/src/queryOptions.ts +++ b/packages/svelte-query/src/queryOptions.ts @@ -1,9 +1,9 @@ import type { - DataTag, DefaultError, InitialDataFunction, NonUndefinedGuard, QueryKey, + QueryKeyWithDataTag, } from '@tanstack/query-core' import type { CreateQueryOptions } from './types.js' @@ -34,9 +34,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: DefinedInitialDataOptions, -): DefinedInitialDataOptions & { - queryKey: DataTag -} +): DefinedInitialDataOptions & + QueryKeyWithDataTag export function queryOptions< TQueryFnData = unknown, @@ -45,9 +44,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: UndefinedInitialDataOptions, -): UndefinedInitialDataOptions & { - queryKey: DataTag -} +): UndefinedInitialDataOptions & + QueryKeyWithDataTag export function queryOptions(options: unknown) { return options diff --git a/packages/svelte-query/tests/queryOptions.test-d.ts b/packages/svelte-query/tests/queryOptions.test-d.ts index 17cb890803d..d7156c1d331 100644 --- a/packages/svelte-query/tests/queryOptions.test-d.ts +++ b/packages/svelte-query/tests/queryOptions.test-d.ts @@ -9,6 +9,13 @@ import { queryKey } from '@tanstack/query-test-utils' import { createQueries, queryOptions } from '../src/index.js' import type { QueryObserverResult } from '@tanstack/query-core' +// Regression test for exported queryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedQueryOptions = queryOptions({ + queryKey: ['invalid'], +}) + describe('queryOptions', () => { it('should not allow excess properties', () => { const key = queryKey() diff --git a/packages/vue-query/src/__tests__/infiniteQueryOptions.test-d.ts b/packages/vue-query/src/__tests__/infiniteQueryOptions.test-d.ts index 2b15cb7bfed..49b5897b388 100644 --- a/packages/vue-query/src/__tests__/infiniteQueryOptions.test-d.ts +++ b/packages/vue-query/src/__tests__/infiniteQueryOptions.test-d.ts @@ -7,6 +7,15 @@ import { QueryClient } from '../queryClient' import { useInfiniteQuery } from '../useInfiniteQuery' import type { InfiniteData } from '@tanstack/query-core' +// Regression test for exported infiniteQueryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedInfiniteQueryOptions = infiniteQueryOptions({ + queryKey: ['invalid'], + getNextPageParam: () => 1, + initialPageParam: 1, +}) + describe('infiniteQueryOptions', () => { it('should not allow excess properties', () => { const key = queryKey() diff --git a/packages/vue-query/src/__tests__/queryOptions.test-d.ts b/packages/vue-query/src/__tests__/queryOptions.test-d.ts index a3e8c6d0d41..2a9361452e7 100644 --- a/packages/vue-query/src/__tests__/queryOptions.test-d.ts +++ b/packages/vue-query/src/__tests__/queryOptions.test-d.ts @@ -6,6 +6,17 @@ import { QueryClient } from '../queryClient' import { queryOptions } from '../queryOptions' import { useQuery } from '../useQuery' +// Regression test for exported queryOptions inference under declaration emit. +// TypeScript should be able to name the return type without expanding the +// internal data tag symbols into the consumer's .d.ts output. +export const exportedQueryOptions = queryOptions({ + queryKey: ['invalid'], +}) + +export const exportedQueryOptionsGetter = queryOptions(() => ({ + queryKey: ['invalid'], +})) + describe('queryOptions', () => { it('should not allow excess properties', () => { const key = queryKey() diff --git a/packages/vue-query/src/index.ts b/packages/vue-query/src/index.ts index 36c616b12af..c58b89cf2a4 100644 --- a/packages/vue-query/src/index.ts +++ b/packages/vue-query/src/index.ts @@ -6,7 +6,11 @@ export { VueQueryPlugin } from './vueQueryPlugin' export { QueryClient } from './queryClient' export { QueryCache } from './queryCache' export { queryOptions } from './queryOptions' -export { type QueryOptions } from './queryOptions' +export type { + QueryOptions, + UndefinedInitialQueryOptionsWithDataTag, + DefinedInitialQueryOptionsWithDataTag, +} from './queryOptions' export { infiniteQueryOptions } from './infiniteQueryOptions' export type { DefinedInitialDataInfiniteOptions, diff --git a/packages/vue-query/src/infiniteQueryOptions.ts b/packages/vue-query/src/infiniteQueryOptions.ts index adab774aa10..ddc34751e7e 100644 --- a/packages/vue-query/src/infiniteQueryOptions.ts +++ b/packages/vue-query/src/infiniteQueryOptions.ts @@ -1,9 +1,9 @@ import type { - DataTag, DefaultError, InfiniteData, NonUndefinedGuard, QueryKey, + QueryKeyWithDataTag, } from '@tanstack/query-core' import type { UseInfiniteQueryOptions } from './useInfiniteQuery' @@ -61,9 +61,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> export function infiniteQueryOptions< TQueryFnData, @@ -85,9 +84,8 @@ export function infiniteQueryOptions< TData, TQueryKey, TPageParam -> & { - queryKey: DataTag, TError> -} +> & + QueryKeyWithDataTag, TError> export function infiniteQueryOptions(options: unknown) { return options diff --git a/packages/vue-query/src/queryOptions.ts b/packages/vue-query/src/queryOptions.ts index 37e7f22b4f5..a0e47548b57 100644 --- a/packages/vue-query/src/queryOptions.ts +++ b/packages/vue-query/src/queryOptions.ts @@ -1,11 +1,11 @@ import type { DeepUnwrapRef, MaybeRefOrGetter, ShallowOption } from './types' import type { - DataTag, DefaultError, InitialDataFunction, NonUndefinedGuard, QueryBooleanOption, QueryKey, + QueryKeyWithDataTag, QueryObserverOptions, } from '@tanstack/query-core' @@ -65,6 +65,22 @@ export type DefinedInitialQueryOptions< | (() => NonUndefinedGuard) } +export type UndefinedInitialQueryOptionsWithDataTag< + TQueryFnData = unknown, + TError = DefaultError, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +> = UndefinedInitialQueryOptions & + QueryKeyWithDataTag + +export type DefinedInitialQueryOptionsWithDataTag< + TQueryFnData = unknown, + TError = DefaultError, + TData = TQueryFnData, + TQueryKey extends QueryKey = QueryKey, +> = DefinedInitialQueryOptions & + QueryKeyWithDataTag + export function queryOptions< TQueryFnData = unknown, TError = DefaultError, @@ -72,9 +88,7 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: DefinedInitialQueryOptions, -): DefinedInitialQueryOptions & { - queryKey: DataTag -} +): DefinedInitialQueryOptionsWithDataTag export function queryOptions< TQueryFnData = unknown, @@ -88,9 +102,12 @@ export function queryOptions< TData, TQueryKey >, -): () => DefinedInitialQueryOptions & { - queryKey: DataTag -} +): () => DefinedInitialQueryOptionsWithDataTag< + TQueryFnData, + TError, + TData, + TQueryKey +> export function queryOptions< TQueryFnData = unknown, @@ -99,9 +116,12 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: UndefinedInitialQueryOptions, -): UndefinedInitialQueryOptions & { - queryKey: DataTag -} +): UndefinedInitialQueryOptionsWithDataTag< + TQueryFnData, + TError, + TData, + TQueryKey +> export function queryOptions< TQueryFnData = unknown, @@ -115,14 +135,12 @@ export function queryOptions< TData, TQueryKey >, -): () => UndefinedInitialQueryOptions< +): () => UndefinedInitialQueryOptionsWithDataTag< TQueryFnData, TError, TData, TQueryKey -> & { - queryKey: DataTag -} +> export function queryOptions(options: unknown) { return options diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f43ddf9e6fb..fb88d2f8587 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2381,6 +2381,19 @@ importers: specifier: ^6.4.1 version: 6.4.1(@types/node@22.19.15)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.90.0)(terser@5.46.1)(tsx@4.21.0)(yaml@2.8.3) + integrations/vue-declaration-emit: + dependencies: + '@tanstack/vue-query': + specifier: workspace:* + version: link:../../packages/vue-query + vue: + specifier: ^3.4.27 + version: 3.5.31(typescript@5.8.3) + devDependencies: + typescript: + specifier: 5.8.3 + version: 5.8.3 + integrations/vue-vite: dependencies: '@tanstack/vue-query':