From c0bda60dbef27664ea2a52897ce09aeeccfa6bae Mon Sep 17 00:00:00 2001 From: TkDodo Date: Mon, 5 May 2025 16:45:34 +0200 Subject: [PATCH 1/5] fix(types): useSuspenseQuery should type-narrow the Error field --- packages/query-core/src/types.ts | 4 ++++ .../src/__tests__/useSuspenseQuery.test-d.tsx | 11 +++++++++++ packages/react-query/src/types.ts | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index f158f0fdd7..c0d3cdb0ee 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -9,6 +9,10 @@ import type { QueryFilters, QueryTypeFilter, SkipToken } from './utils' import type { QueryCache } from './queryCache' import type { MutationCache } from './mutationCache' +export type DistributiveOmit = TKey extends any + ? Pick> + : never + export type OmitKeyof< TObject, TKey extends TStrictly extends 'safely' diff --git a/packages/react-query/src/__tests__/useSuspenseQuery.test-d.tsx b/packages/react-query/src/__tests__/useSuspenseQuery.test-d.tsx index 847a0f8c38..09576d63b8 100644 --- a/packages/react-query/src/__tests__/useSuspenseQuery.test-d.tsx +++ b/packages/react-query/src/__tests__/useSuspenseQuery.test-d.tsx @@ -68,4 +68,15 @@ describe('useSuspenseQuery', () => { // @ts-expect-error TS2339 query.isPlaceholderData }) + + it('should type-narrow the error field', () => { + const query = useSuspenseQuery({ + queryKey: ['key'], + queryFn: () => Promise.resolve(5), + }) + + if (query.status === 'error') { + expectTypeOf(query.error).toEqualTypeOf() + } + }) }) diff --git a/packages/react-query/src/types.ts b/packages/react-query/src/types.ts index 1609425301..18f632d406 100644 --- a/packages/react-query/src/types.ts +++ b/packages/react-query/src/types.ts @@ -4,6 +4,7 @@ import type { DefaultError, DefinedInfiniteQueryObserverResult, DefinedQueryObserverResult, + DistributiveOmit, InfiniteQueryObserverOptions, InfiniteQueryObserverResult, MutateFunction, @@ -155,7 +156,7 @@ export type UseQueryResult< export type UseSuspenseQueryResult< TData = unknown, TError = DefaultError, -> = OmitKeyof< +> = DistributiveOmit< DefinedQueryObserverResult, 'isPlaceholderData' | 'promise' > From 70e3f17b3c662759c7890012a3e1b6ee846ccf63 Mon Sep 17 00:00:00 2001 From: Dominik Dorfmeister Date: Mon, 5 May 2025 20:25:58 +0200 Subject: [PATCH 2/5] Update packages/query-core/src/types.ts Co-authored-by: Jonghyeon Ko --- packages/query-core/src/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index c0d3cdb0ee..7877c8b87d 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -9,8 +9,8 @@ import type { QueryFilters, QueryTypeFilter, SkipToken } from './utils' import type { QueryCache } from './queryCache' import type { MutationCache } from './mutationCache' -export type DistributiveOmit = TKey extends any - ? Pick> +export type DistributiveOmit = TObject extends any + ? Pick> : never export type OmitKeyof< From 6b8cf8e66999640d39172e67ea67f0d1b6850863 Mon Sep 17 00:00:00 2001 From: Dominik Dorfmeister Date: Tue, 6 May 2025 09:10:58 +0200 Subject: [PATCH 3/5] Update packages/query-core/src/types.ts Co-authored-by: Jonghyeon Ko --- packages/query-core/src/types.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/query-core/src/types.ts b/packages/query-core/src/types.ts index 7877c8b87d..dfde4ef867 100644 --- a/packages/query-core/src/types.ts +++ b/packages/query-core/src/types.ts @@ -9,9 +9,10 @@ import type { QueryFilters, QueryTypeFilter, SkipToken } from './utils' import type { QueryCache } from './queryCache' import type { MutationCache } from './mutationCache' -export type DistributiveOmit = TObject extends any - ? Pick> - : never +export type DistributiveOmit< + TObject, + TKey extends keyof TObject, +> = TObject extends any ? Omit : never export type OmitKeyof< TObject, From 961e4e86bd73b42f7a0218358eca98c29dc263b0 Mon Sep 17 00:00:00 2001 From: TkDodo Date: Tue, 6 May 2025 09:12:06 +0200 Subject: [PATCH 4/5] ref: use DistributiveOmit from query-core in vue-query --- packages/vue-query/src/types.ts | 4 ---- packages/vue-query/src/useMutation.ts | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/vue-query/src/types.ts b/packages/vue-query/src/types.ts index a0c9fbaf5d..afabb55ea3 100644 --- a/packages/vue-query/src/types.ts +++ b/packages/vue-query/src/types.ts @@ -55,10 +55,6 @@ export type DeepUnwrapRef = T extends UnwrapLeaf } : UnwrapRef -export type DistributiveOmit = T extends any - ? Omit - : never - export interface DefaultOptions { queries?: OmitKeyof, 'queryKey'> & { /** diff --git a/packages/vue-query/src/useMutation.ts b/packages/vue-query/src/useMutation.ts index c8f490b3f9..62c207b1ea 100644 --- a/packages/vue-query/src/useMutation.ts +++ b/packages/vue-query/src/useMutation.ts @@ -15,12 +15,13 @@ import { useQueryClient } from './useQueryClient' import type { ToRefs } from 'vue-demi' import type { DefaultError, + DistributiveOmit, MutateFunction, MutateOptions, MutationObserverOptions, MutationObserverResult, } from '@tanstack/query-core' -import type { DistributiveOmit, MaybeRefDeep } from './types' +import type { MaybeRefDeep } from './types' import type { QueryClient } from './queryClient' type MutationResult = DistributiveOmit< From 027321044648221483880720b88db850c76045ee Mon Sep 17 00:00:00 2001 From: TkDodo Date: Tue, 6 May 2025 09:14:44 +0200 Subject: [PATCH 5/5] chore: fix type error in tests --- packages/react-query/src/__tests__/useSuspenseQuery.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-query/src/__tests__/useSuspenseQuery.test.tsx b/packages/react-query/src/__tests__/useSuspenseQuery.test.tsx index 922efdbd2a..d86e710cd0 100644 --- a/packages/react-query/src/__tests__/useSuspenseQuery.test.tsx +++ b/packages/react-query/src/__tests__/useSuspenseQuery.test.tsx @@ -703,7 +703,7 @@ describe('useSuspenseQuery', () => { it('should render the correct amount of times in Suspense mode when gcTime is set to 0', async () => { const key = queryKey() - let state: UseSuspenseQueryResult | null = null + let state: UseSuspenseQueryResult | null = null let count = 0 let renders = 0