From 67c2a8a0992977728e1fbb212a9e00902373c583 Mon Sep 17 00:00:00 2001 From: TkDodo Date: Tue, 18 Aug 2026 16:31:45 +0200 Subject: [PATCH 1/3] integration test --- .../consumer/query-options.ts | 9 +++++++ .../vue-declaration-emit/package.json | 26 +++++++++++++++++++ .../vue-declaration-emit/src/query-options.ts | 14 ++++++++++ .../tsconfig.consume.json | 11 ++++++++ .../vue-declaration-emit/tsconfig.emit.json | 13 ++++++++++ pnpm-lock.yaml | 13 ++++++++++ 6 files changed, 86 insertions(+) create mode 100644 integrations/vue-declaration-emit/consumer/query-options.ts create mode 100644 integrations/vue-declaration-emit/package.json create mode 100644 integrations/vue-declaration-emit/src/query-options.ts create mode 100644 integrations/vue-declaration-emit/tsconfig.consume.json create mode 100644 integrations/vue-declaration-emit/tsconfig.emit.json 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 0000000000..8bdcbeef9f --- /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 0000000000..a7d3455be6 --- /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 0000000000..4fcfcd16ed --- /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 0000000000..6cba091b2c --- /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 0000000000..7206033e8e --- /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/pnpm-lock.yaml b/pnpm-lock.yaml index f43ddf9e6f..fb88d2f858 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': From 328bc78e19b2427e59f346d6c6c9d00694d30763 Mon Sep 17 00:00:00 2001 From: TkDodo Date: Tue, 18 Aug 2026 16:58:07 +0200 Subject: [PATCH 2/3] fix: declaration emit --- .../fix-query-options-declaration-emit.md | 11 +++++ .../infinite-query-options.test-d.ts | 9 ++++ .../src/__tests__/query-options.test-d.ts | 7 +++ .../src/infinite-query-options.ts | 17 +++---- .../src/query-options.ts | 17 +++---- .../__tests__/infiniteQueryOptions.test-d.tsx | 9 ++++ .../src/__tests__/queryOptions.test-d.tsx | 7 +++ .../preact-query/src/infiniteQueryOptions.ts | 17 +++---- packages/preact-query/src/queryOptions.ts | 17 +++---- packages/query-core/src/types.ts | 8 ++++ .../__tests__/infiniteQueryOptions.test-d.tsx | 9 ++++ .../src/__tests__/queryOptions.test-d.tsx | 7 +++ .../react-query/src/infiniteQueryOptions.ts | 17 +++---- packages/react-query/src/queryOptions.ts | 17 +++---- .../__tests__/infiniteQueryOptions.test-d.tsx | 9 ++++ .../src/__tests__/queryOptions.test-d.tsx | 7 +++ .../solid-query/src/infiniteQueryOptions.ts | 12 ++--- packages/solid-query/src/queryOptions.ts | 16 ++++--- packages/svelte-query/src/queryOptions.ts | 12 ++--- .../svelte-query/tests/queryOptions.test-d.ts | 7 +++ .../__tests__/infiniteQueryOptions.test-d.ts | 9 ++++ .../src/__tests__/queryOptions.test-d.ts | 11 +++++ packages/vue-query/src/index.ts | 6 ++- .../vue-query/src/infiniteQueryOptions.ts | 12 ++--- packages/vue-query/src/queryOptions.ts | 46 +++++++++++++------ 25 files changed, 213 insertions(+), 103 deletions(-) create mode 100644 .changeset/fix-query-options-declaration-emit.md diff --git a/.changeset/fix-query-options-declaration-emit.md b/.changeset/fix-query-options-declaration-emit.md new file mode 100644 index 0000000000..fc700263aa --- /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/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 9c11ce039e..e9f41ed3b6 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 c6a0e6d8fd..c4462afaa3 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 0bed440730..b09b194c6b 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 14a50074b0..4f6897618e 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 047d877ac3..563e7a6911 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 4fd5c37e8f..9b0c518316 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 6e1e0be3bc..660f00b1de 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 bdf19e9758..3b61de0912 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 b71039d332..a413376d46 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 4f72db57d4..ae160129ca 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 dfeedcff64..a818a00e45 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 5e8c371a59..bccc9699da 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 644ac26788..852a6c3b61 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 39978d9658..be3a19cb97 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 88f811bb77..05672ba10c 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 6f4885d999..1648882d2f 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 fea9db1e1f..55e16871ea 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 e1a44be631..da5e0b42b8 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 17cb890803..d7156c1d33 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 2b15cb7bfe..49b5897b38 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 a3e8c6d0d4..2a9361452e 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 36c616b12a..c58b89cf2a 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 adab774aa1..ddc34751e7 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 37e7f22b4f..a0e47548b5 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 From b875997fda68bce0e211f3d1a870e3502271f8a3 Mon Sep 17 00:00:00 2001 From: TkDodo Date: Tue, 18 Aug 2026 17:39:53 +0200 Subject: [PATCH 3/3] fix: TError forwarding in svelte --- packages/svelte-query/src/queryOptions.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/svelte-query/src/queryOptions.ts b/packages/svelte-query/src/queryOptions.ts index da5e0b42b8..1511ba85a6 100644 --- a/packages/svelte-query/src/queryOptions.ts +++ b/packages/svelte-query/src/queryOptions.ts @@ -35,7 +35,7 @@ export function queryOptions< >( options: DefinedInitialDataOptions, ): DefinedInitialDataOptions & - QueryKeyWithDataTag + QueryKeyWithDataTag export function queryOptions< TQueryFnData = unknown, @@ -45,7 +45,7 @@ export function queryOptions< >( options: UndefinedInitialDataOptions, ): UndefinedInitialDataOptions & - QueryKeyWithDataTag + QueryKeyWithDataTag export function queryOptions(options: unknown) { return options