Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/fix-query-options-declaration-emit.md
Original file line numberDiff line numberDiff line change
@@ -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.
9 changes: 9 additions & 0 deletions integrations/vue-declaration-emit/consumer/query-options.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
import{
definedInitialDataOptions,
undefinedInitialDataOptions,
}from'../dist/query-options.js'

exportconstoptions={
definedInitialDataOptions,
undefinedInitialDataOptions,
}
26 changes: 26 additions & 0 deletions integrations/vue-declaration-emit/package.json
Original file line numberDiff line numberDiff line change
@@ -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"
]
}
}
}
}
14 changes: 14 additions & 0 deletions integrations/vue-declaration-emit/src/query-options.ts
Original file line numberDiff line numberDiff line change
@@ -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' },
})
11 changes: 11 additions & 0 deletions integrations/vue-declaration-emit/tsconfig.consume.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"noEmit": true,
"skipLibCheck": false,
"strict": true
},
"include": ["./consumer"]
}
13 changes: 13 additions & 0 deletions integrations/vue-declaration-emit/tsconfig.emit.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"declaration": true,
"emitDeclarationOnly": true,
"strict": true,
"rootDir": "./src",
"outDir": "./dist"
},
"include": ["./src"]
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -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()
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -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')
Expand Down
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
import type {
DataTag,
DefaultError,
InfiniteData,
InitialDataFunction,
NonUndefinedGuard,
OmitKeyof,
QueryKey,
QueryKeyWithDataTag,
SkipToken,
} from '@tanstack/query-core'
import type { CreateInfiniteQueryOptions } from './types'
Expand DownExpand Up@@ -105,9 +105,8 @@ export function infiniteQueryOptions<
TData,
TQueryKey,
TPageParam
> & {
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
}
> &
QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>

/**
* Allows sharing and re-using infinite query options in a type-safe way.
Expand DownExpand Up@@ -136,9 +135,8 @@ export function infiniteQueryOptions<
TData,
TQueryKey,
TPageParam
> & {
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
}
> &
QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>

/**
* Allows sharing and re-using infinite query options in a type-safe way.
Expand DownExpand Up@@ -167,9 +165,8 @@ export function infiniteQueryOptions<
TData,
TQueryKey,
TPageParam
> & {
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
}
> &
QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>

/**
* Allows sharing and re-using infinite query options in a type-safe way.
Expand Down
17 changes: 7 additions & 10 deletions packages/angular-query-experimental/src/query-options.ts
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
import type {
DataTag,
DefaultError,
InitialDataFunction,
NonUndefinedGuard,
OmitKeyof,
QueryFunction,
QueryKey,
QueryKeyWithDataTag,
SkipToken,
} from '@tanstack/query-core'
import type { CreateQueryOptions } from './types'
Expand DownExpand Up@@ -80,9 +80,8 @@ export function queryOptions<
TQueryKey extends QueryKey = QueryKey,
>(
options: DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,
): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
}
): DefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> &
QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>

/**
* Allows sharing and re-using query options in a type-safe way.
Expand DownExpand Up@@ -112,9 +111,8 @@ export function queryOptions<
TQueryKey extends QueryKey = QueryKey,
>(
options: UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey>,
): UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> & {
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
}
): UnusedSkipTokenOptions<TQueryFnData, TError, TData, TQueryKey> &
QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>

/**
* Allows sharing and re-using query options in a type-safe way.
Expand DownExpand Up@@ -144,9 +142,8 @@ export function queryOptions<
TQueryKey extends QueryKey = QueryKey,
>(
options: UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey>,
): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> & {
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
}
): UndefinedInitialDataOptions<TQueryFnData, TError, TData, TQueryKey> &
QueryKeyWithDataTag<TQueryKey, TQueryFnData, TError>

/**
* Allows sharing and re-using query options in a type-safe way.
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -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(
Expand Down
7 changes: 7 additions & 0 deletions packages/preact-query/src/__tests__/queryOptions.test-d.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -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(
Expand Down
17 changes: 7 additions & 10 deletions packages/preact-query/src/infiniteQueryOptions.ts
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
import type {
DataTag,
DefaultError,
InfiniteData,
InitialDataFunction,
NonUndefinedGuard,
OmitKeyof,
QueryKey,
QueryKeyWithDataTag,
SkipToken,
} from '@tanstack/query-core'

Expand DownExpand Up@@ -93,9 +93,8 @@ export function infiniteQueryOptions<
TData,
TQueryKey,
TPageParam
> & {
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
}
> &
QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>

export function infiniteQueryOptions<
TQueryFnData,
Expand All@@ -117,9 +116,8 @@ export function infiniteQueryOptions<
TData,
TQueryKey,
TPageParam
> & {
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
}
> &
QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>

export function infiniteQueryOptions<
TQueryFnData,
Expand All@@ -141,9 +139,8 @@ export function infiniteQueryOptions<
TData,
TQueryKey,
TPageParam
> & {
queryKey: DataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>
}
> &
QueryKeyWithDataTag<TQueryKey, InfiniteData<TQueryFnData>, TError>

export function infiniteQueryOptions(options: unknown) {
return options
Expand Down
17 changes: 7 additions & 10 deletions packages/preact-query/src/queryOptions.ts
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
importtype{
DataTag,
DefaultError,
InitialDataFunction,
NonUndefinedGuard,
OmitKeyof,
QueryFunction,
QueryKey,
QueryKeyWithDataTag,
SkipToken,
}from'@tanstack/query-core'

Expand DownExpand Up@@ -57,9 +57,8 @@ export function queryOptions<
TQueryKeyextendsQueryKey=QueryKey,
>(
options: DefinedInitialDataOptions<TQueryFnData,TError,TData,TQueryKey>,
): DefinedInitialDataOptions<TQueryFnData,TError,TData,TQueryKey>&{
queryKey: DataTag<TQueryKey,TQueryFnData,TError>
}
): DefinedInitialDataOptions<TQueryFnData,TError,TData,TQueryKey>&
QueryKeyWithDataTag<TQueryKey,TQueryFnData,TError>

exportfunctionqueryOptions<
TQueryFnData=unknown,
Expand All@@ -68,9 +67,8 @@ export function queryOptions<
TQueryKeyextendsQueryKey=QueryKey,
>(
options: UnusedSkipTokenOptions<TQueryFnData,TError,TData,TQueryKey>,
): UnusedSkipTokenOptions<TQueryFnData,TError,TData,TQueryKey>&{
queryKey: DataTag<TQueryKey,TQueryFnData,TError>
}
): UnusedSkipTokenOptions<TQueryFnData,TError,TData,TQueryKey>&
QueryKeyWithDataTag<TQueryKey,TQueryFnData,TError>

exportfunctionqueryOptions<
TQueryFnData=unknown,
Expand All@@ -79,9 +77,8 @@ export function queryOptions<
TQueryKeyextendsQueryKey=QueryKey,
>(
options: UndefinedInitialDataOptions<TQueryFnData,TError,TData,TQueryKey>,
): UndefinedInitialDataOptions<TQueryFnData,TError,TData,TQueryKey>&{
queryKey: DataTag<TQueryKey,TQueryFnData,TError>
}
): UndefinedInitialDataOptions<TQueryFnData,TError,TData,TQueryKey>&
QueryKeyWithDataTag<TQueryKey,TQueryFnData,TError>

exportfunctionqueryOptions(options: unknown){
returnoptions
Expand Down
8 changes: 8 additions & 0 deletions packages/query-core/src/types.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,6 +79,14 @@ export type DataTag<
[dataTagErrorSymbol]: TError
}

export type QueryKeyWithDataTag<
TQueryKey extends QueryKey = QueryKey,
TQueryFnData = unknown,
TError = DefaultError,
> = {
queryKey: DataTag<TQueryKey, TQueryFnData, TError>
}

export type InferDataFromTag<TQueryFnData, TTaggedQueryKey extends QueryKey> =
TTaggedQueryKey extends DataTag<unknown, infer TaggedValue, unknown>
? TaggedValue
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -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(
Expand Down
7 changes: 7 additions & 0 deletions packages/react-query/src/__tests__/queryOptions.test-d.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -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(
Expand Down
Loading
Loading