From 00bd10ea3d01e21e2d14f1f0ba191e843c14e9be Mon Sep 17 00:00:00 2001 From: Nick Lucas Date: Tue, 3 Dec 2024 22:16:23 +0000 Subject: [PATCH 1/7] Fix issues with queryOptions factory method types --- .../src/__tests__/queryClient.test-d.tsx | 9 ++--- .../query-core/src/__tests__/utils.test-d.tsx | 4 +-- packages/query-core/src/types.ts | 16 +++++++-- .../src/__tests__/queryOptions.test-d.tsx | 34 ++++++++++++++++++- packages/react-query/src/queryOptions.ts | 10 +++--- 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/packages/query-core/src/__tests__/queryClient.test-d.tsx b/packages/query-core/src/__tests__/queryClient.test-d.tsx index 4f0d42fc84..ddde0903ad 100644 --- a/packages/query-core/src/__tests__/queryClient.test-d.tsx +++ b/packages/query-core/src/__tests__/queryClient.test-d.tsx @@ -228,16 +228,11 @@ describe('fully typed usage', () => { TData, TError, TData, - QueryKey & DataTag + DataTag > = { predicate(query) { expectTypeOf(query).toEqualTypeOf< - Query< - TData, - TError, - TData, - QueryKey & DataTag - > + Query> >() expectTypeOf(query.state.data).toEqualTypeOf() expectTypeOf(query.state.error).toEqualTypeOf() diff --git a/packages/query-core/src/__tests__/utils.test-d.tsx b/packages/query-core/src/__tests__/utils.test-d.tsx index 2c602ddc3b..91be29f3d4 100644 --- a/packages/query-core/src/__tests__/utils.test-d.tsx +++ b/packages/query-core/src/__tests__/utils.test-d.tsx @@ -11,7 +11,7 @@ describe('QueryFilters', () => { TData, Error, TData, - QueryKey & DataTag + DataTag > = { predicate(query) { expectTypeOf(query.setData({ a: 1, b: '1' })).toEqualTypeOf() @@ -37,7 +37,7 @@ describe('QueryFilters', () => { TData, TError, TData, - QueryKey & DataTag + DataTag > = { predicate(query) { expectTypeOf(query.setData({ a: 1, b: '1' })).toEqualTypeOf() diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index a21016bf2c..ea43533811 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -46,10 +46,20 @@ export declare const dataTagSymbol: unique symbol export declare const dataTagErrorSymbol: unique symbol export declare const unsetMarker: unique symbol export type UnsetMarker = typeof unsetMarker -export type DataTag = TType & { - [dataTagSymbol]: TValue - [dataTagErrorSymbol]: TError +export type AnyDataTag = { + [dataTagSymbol]: any + [dataTagErrorSymbol]: any } +export type DataTag< + TType, + TValue, + TError = UnsetMarker, +> = TType extends AnyDataTag + ? TType + : TType & { + [dataTagSymbol]: TValue + [dataTagErrorSymbol]: TError + } export type QueryFunction< T = unknown, diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index 414a621623..63bc347184 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -11,7 +11,9 @@ import { useQueries } from '../useQueries' import { useSuspenseQuery } from '../useSuspenseQuery' import type { UseQueryOptions } from '../types' import type { + DataTag, InitialDataFunction, + QueryKey, QueryObserverResult, } from '@tanstack/query-core' @@ -241,10 +243,40 @@ describe('queryOptions', () => { } const options = queryOptions({ - queryKey: ['key'], + queryKey: ['key'] as QueryKey, queryFn: () => Promise.resolve(1), }) somethingWithQueryOptions(options) }) + + it('should return a custom query key type', () => { + type MyQueryKey = [Array, { type: 'foo' }] + + const options = queryOptions({ + queryKey: [['key'], { type: 'foo' }] as MyQueryKey, + queryFn: () => Promise.resolve(1), + }) + + expectTypeOf(options.queryKey).toEqualTypeOf< + DataTag + >() + }) + + it('should return a custom query key type with datatag', () => { + type MyQueryKey = DataTag< + [Array, { type: 'foo' }], + number, + Error & { myMessage: string } + > + + const options = queryOptions({ + queryKey: [['key'], { type: 'foo' }] as MyQueryKey, + queryFn: () => Promise.resolve(1), + }) + + expectTypeOf(options.queryKey).toEqualTypeOf< + DataTag + >() + }) }) diff --git a/packages/react-query/src/queryOptions.ts b/packages/react-query/src/queryOptions.ts index b137d9688d..714d38a5f7 100644 --- a/packages/react-query/src/queryOptions.ts +++ b/packages/react-query/src/queryOptions.ts @@ -55,8 +55,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: DefinedInitialDataOptions, -): DefinedInitialDataOptions & { - queryKey: DataTag +): DefinedInitialDataOptions & { + queryKey: DataTag } export function queryOptions< @@ -66,8 +66,8 @@ export function queryOptions< TQueryKey extends QueryKey = QueryKey, >( options: UnusedSkipTokenOptions, -): UnusedSkipTokenOptions & { - queryKey: DataTag +): UnusedSkipTokenOptions & { + queryKey: DataTag } export function queryOptions< @@ -78,7 +78,7 @@ export function queryOptions< >( options: UndefinedInitialDataOptions, ): UndefinedInitialDataOptions & { - queryKey: DataTag + queryKey: DataTag } export function queryOptions(options: unknown) { From f3deaf1a49d6ea8c9145aed02d8ae155f0ba4ed6 Mon Sep 17 00:00:00 2001 From: Nick Lucas Date: Wed, 4 Dec 2024 14:03:25 +0000 Subject: [PATCH 2/7] Apply the same fixes to infiniteQueryOptions --- .../__tests__/infiniteQueryOptions.test-d.tsx | 40 ++++++++++++++++++- .../src/__tests__/queryOptions.test-d.tsx | 2 +- .../react-query/src/infiniteQueryOptions.ts | 6 +-- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx b/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx index 363ea1b37c..c5d7efeee9 100644 --- a/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/infiniteQueryOptions.test-d.tsx @@ -4,7 +4,11 @@ import { infiniteQueryOptions } from '../infiniteQueryOptions' import { useInfiniteQuery } from '../useInfiniteQuery' import { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery' import { useQuery } from '../useQuery' -import type { InfiniteData, InitialDataFunction } from '@tanstack/query-core' +import type { + DataTag, + InfiniteData, + InitialDataFunction, +} from '@tanstack/query-core' describe('infiniteQueryOptions', () => { it('should not allow excess properties', () => { @@ -200,4 +204,38 @@ describe('infiniteQueryOptions', () => { | undefined >() }) + + it('should return a custom query key type', () => { + type MyQueryKey = [Array, { type: 'foo' }] + + const options = infiniteQueryOptions({ + queryKey: [['key'], { type: 'foo' }] as MyQueryKey, + queryFn: () => Promise.resolve(1), + getNextPageParam: () => 1, + initialPageParam: 1, + }) + + expectTypeOf(options.queryKey).toEqualTypeOf< + DataTag, Error> + >() + }) + + it('should return a custom query key type with datatag', () => { + type MyQueryKey = DataTag< + [Array, { type: 'foo' }], + number, + Error & { myMessage: string } + > + + const options = infiniteQueryOptions({ + queryKey: [['key'], { type: 'foo' }] as MyQueryKey, + queryFn: () => Promise.resolve(1), + getNextPageParam: () => 1, + initialPageParam: 1, + }) + + expectTypeOf(options.queryKey).toEqualTypeOf< + DataTag, Error & { myMessage: string }> + >() + }) }) diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index 63bc347184..238a08d4cf 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -243,7 +243,7 @@ describe('queryOptions', () => { } const options = queryOptions({ - queryKey: ['key'] as QueryKey, + queryKey: ['key'] as Array, queryFn: () => Promise.resolve(1), }) diff --git a/packages/react-query/src/infiniteQueryOptions.ts b/packages/react-query/src/infiniteQueryOptions.ts index 594c4217e2..d834bd5987 100644 --- a/packages/react-query/src/infiniteQueryOptions.ts +++ b/packages/react-query/src/infiniteQueryOptions.ts @@ -104,7 +104,7 @@ export function infiniteQueryOptions< TQueryKey, TPageParam > & { - queryKey: DataTag> + queryKey: DataTag, TError> } export function infiniteQueryOptions< @@ -128,7 +128,7 @@ export function infiniteQueryOptions< TQueryKey, TPageParam > & { - queryKey: DataTag> + queryKey: DataTag, TError> } export function infiniteQueryOptions< @@ -152,7 +152,7 @@ export function infiniteQueryOptions< TQueryKey, TPageParam > & { - queryKey: DataTag> + queryKey: DataTag, TError> } export function infiniteQueryOptions(options: unknown) { From 59313c073189f2eefb1ee94ec99ddbf9997703df Mon Sep 17 00:00:00 2001 From: Nick Lucas Date: Wed, 4 Dec 2024 20:38:41 +0000 Subject: [PATCH 3/7] Revert change to failing test --- packages/react-query/src/__tests__/queryOptions.test-d.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index 238a08d4cf..a4aa37d39f 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -243,7 +243,7 @@ describe('queryOptions', () => { } const options = queryOptions({ - queryKey: ['key'] as Array, + queryKey: ['key'], queryFn: () => Promise.resolve(1), }) From 2c4ec391e13c5437408e993ba43c171c463fb280 Mon Sep 17 00:00:00 2001 From: Nick Lucas Date: Wed, 4 Dec 2024 20:45:03 +0000 Subject: [PATCH 4/7] Fix test in more userland way --- packages/react-query/src/__tests__/queryOptions.test-d.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index a4aa37d39f..92b3503b6f 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -238,7 +238,9 @@ describe('queryOptions', () => { }) it('should be passable to UseQueryOptions', () => { - function somethingWithQueryOptions(options: UseQueryOptions) { + function somethingWithQueryOptions( + options: UseQueryOptions>, + ) { return options.queryKey } From 1f7d0b2d54cf902a33c69d0a15129f456258e5f8 Mon Sep 17 00:00:00 2001 From: Nick Lucas Date: Wed, 4 Dec 2024 20:54:58 +0000 Subject: [PATCH 5/7] Unused import --- packages/react-query/src/__tests__/queryOptions.test-d.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index 92b3503b6f..01f6d73978 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -13,7 +13,6 @@ import type { UseQueryOptions } from '../types' import type { DataTag, InitialDataFunction, - QueryKey, QueryObserverResult, } from '@tanstack/query-core' From 9623166c4a1d7d1268cf2a348330f50e36769e75 Mon Sep 17 00:00:00 2001 From: Nick Lucas Date: Wed, 11 Dec 2024 21:56:47 +0000 Subject: [PATCH 6/7] Add tRPC-style solution --- .../src/__tests__/queryOptions.test-d.tsx | 6 ++--- packages/react-query/src/types.ts | 25 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index 01f6d73978..4734294d04 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -9,7 +9,7 @@ import { queryOptions } from '../queryOptions' import { useQuery } from '../useQuery' import { useQueries } from '../useQueries' import { useSuspenseQuery } from '../useSuspenseQuery' -import type { UseQueryOptions } from '../types' +import type { AnyUseQueryOptions, UseQueryOptions } from '../types' import type { DataTag, InitialDataFunction, @@ -237,8 +237,8 @@ describe('queryOptions', () => { }) it('should be passable to UseQueryOptions', () => { - function somethingWithQueryOptions( - options: UseQueryOptions>, + function somethingWithQueryOptions( + options: TQueryOpts, ) { return options.queryKey } diff --git a/packages/react-query/src/types.ts b/packages/react-query/src/types.ts index 8516536361..9f6d7c315f 100644 --- a/packages/react-query/src/types.ts +++ b/packages/react-query/src/types.ts @@ -17,6 +17,13 @@ import type { SkipToken, } from '@tanstack/query-core' +export type AnyUseBaseQueryOptions = UseBaseQueryOptions< + any, + any, + any, + any, + any +> export interface UseBaseQueryOptions< TQueryFnData = unknown, TError = DefaultError, @@ -31,6 +38,7 @@ export interface UseBaseQueryOptions< TQueryKey > {} +export type AnyUseQueryOptions = UseQueryOptions export interface UseQueryOptions< TQueryFnData = unknown, TError = DefaultError, @@ -41,6 +49,12 @@ export interface UseQueryOptions< 'suspense' > {} +export type AnyUseSuspenseQueryOptions = UseSuspenseQueryOptions< + any, + any, + any, + any +> export interface UseSuspenseQueryOptions< TQueryFnData = unknown, TError = DefaultError, @@ -56,6 +70,14 @@ export interface UseSuspenseQueryOptions< > } +export type AnyUseInfiniteQueryOptions = UseInfiniteQueryOptions< + any, + any, + any, + any, + any, + any +> export interface UseInfiniteQueryOptions< TQueryFnData = unknown, TError = DefaultError, @@ -75,6 +97,8 @@ export interface UseInfiniteQueryOptions< 'suspense' > {} +export type AnyUseSuspenseInfiniteQueryOptions = + UseSuspenseInfiniteQueryOptions export interface UseSuspenseInfiniteQueryOptions< TQueryFnData = unknown, TError = DefaultError, @@ -147,6 +171,7 @@ export type UseSuspenseInfiniteQueryResult< 'isPlaceholderData' | 'promise' > +export type AnyUseMutationOptions = UseMutationOptions export interface UseMutationOptions< TData = unknown, TError = DefaultError, From e4647407c51fc901aea2ca61b964c5a08b40be38 Mon Sep 17 00:00:00 2001 From: Nick Lucas Date: Wed, 11 Dec 2024 22:14:34 +0000 Subject: [PATCH 7/7] Unused import --- packages/react-query/src/__tests__/queryOptions.test-d.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-query/src/__tests__/queryOptions.test-d.tsx b/packages/react-query/src/__tests__/queryOptions.test-d.tsx index 4734294d04..eb34463856 100644 --- a/packages/react-query/src/__tests__/queryOptions.test-d.tsx +++ b/packages/react-query/src/__tests__/queryOptions.test-d.tsx @@ -9,7 +9,7 @@ import { queryOptions } from '../queryOptions' import { useQuery } from '../useQuery' import { useQueries } from '../useQueries' import { useSuspenseQuery } from '../useSuspenseQuery' -import type { AnyUseQueryOptions, UseQueryOptions } from '../types' +import type { AnyUseQueryOptions } from '../types' import type { DataTag, InitialDataFunction,