From e3b11c01595b61c3844b0b2a3d345e91ab98249c Mon Sep 17 00:00:00 2001 From: mdm317 Date: Sun, 14 Sep 2025 16:05:36 +0900 Subject: [PATCH 1/5] fix: narrow injectInfiniteQuery type with initial data --- .../__tests__/inject-infinite-query.test-d.ts | 127 ++++++++++++++++-- .../angular-query-experimental/src/types.ts | 3 +- 2 files changed, 116 insertions(+), 14 deletions(-) diff --git a/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts b/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts index 7ec133adfb..588e85af17 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts +++ b/packages/angular-query-experimental/src/__tests__/inject-infinite-query.test-d.ts @@ -23,20 +23,121 @@ describe('injectInfiniteQuery', () => { vi.useRealTimers() }) - test('should narrow type after isSuccess', () => { - const query = TestBed.runInInjectionContext(() => { - return injectInfiniteQuery(() => ({ - queryKey: ['infiniteQuery'], - queryFn: ({ pageParam }) => - sleep(0).then(() => 'data on page ' + pageParam), - initialPageParam: 0, - getNextPageParam: () => 12, - })) + describe('without initialData', () => { + test('should narrow type after isSuccess', () => { + const query = TestBed.runInInjectionContext(() => { + return injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + sleep(0).then(() => 'data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + }) + + if (query.isSuccess()) { + const data = query.data() + expectTypeOf(data).toEqualTypeOf>() + } + }) + + test('should narrow type after isPending', () => { + const query = TestBed.runInInjectionContext(() => { + return injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + sleep(0).then(() => 'data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + }) + + if (query.isPending()) { + const data = query.data() + expectTypeOf(data).toEqualTypeOf() + } + }) + + test('should narrow type after isError', () => { + const query = TestBed.runInInjectionContext(() => { + return injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + sleep(0).then(() => 'data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + })) + }) + + if (query.isError()) { + const error = query.error() + expectTypeOf(error).toEqualTypeOf() + } + }) + }) + + describe('with initialData', () => { + test('should narrow type after isSuccess', () => { + const query = TestBed.runInInjectionContext(() => { + return injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + sleep(0).then(() => 'data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + initialData: { + pageParams: [0, 1], + pages: ['page 0 data', 'page 1 data'], + }, + })) + }) + + if (query.isSuccess()) { + const data = query.data() + expectTypeOf(data).toEqualTypeOf>() + } + }) + + test('should narrow type after isPending', () => { + const query = TestBed.runInInjectionContext(() => { + return injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + sleep(0).then(() => 'data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + initialData: { + pageParams: [0, 1], + pages: ['page 0 data', 'page 1 data'], + }, + })) + }) + + if (query.isPending()) { + const data = query.data() + expectTypeOf(data).toEqualTypeOf>() + } }) - if (query.isSuccess()) { - const data = query.data() - expectTypeOf(data).toEqualTypeOf>() - } + test('should narrow type after isError', () => { + const query = TestBed.runInInjectionContext(() => { + return injectInfiniteQuery(() => ({ + queryKey: ['infiniteQuery'], + queryFn: ({ pageParam }) => + sleep(0).then(() => 'data on page ' + pageParam), + initialPageParam: 0, + getNextPageParam: () => 12, + initialData: { + pageParams: [0, 1], + pages: ['page 0 data', 'page 1 data'], + }, + })) + }) + + if (query.isError()) { + const error = query.error() + expectTypeOf(error).toEqualTypeOf() + } + }) }) }) diff --git a/packages/angular-query-experimental/src/types.ts b/packages/angular-query-experimental/src/types.ts index 7c5e3638c3..9f3c4d103b 100644 --- a/packages/angular-query-experimental/src/types.ts +++ b/packages/angular-query-experimental/src/types.ts @@ -157,7 +157,8 @@ export type DefinedCreateInfiniteQueryResult< TData, TError >, -> = MapToSignals +> =BaseQueryNarrowing & + MapToSignals export interface CreateMutationOptions< TData = unknown, From 7744947b20aadf911e183bceab5eea37624dcd2a Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sun, 14 Sep 2025 16:00:16 +0000 Subject: [PATCH 2/5] ci: apply automated fixes --- packages/angular-query-experimental/src/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/angular-query-experimental/src/types.ts b/packages/angular-query-experimental/src/types.ts index 9f3c4d103b..a41f24625c 100644 --- a/packages/angular-query-experimental/src/types.ts +++ b/packages/angular-query-experimental/src/types.ts @@ -157,8 +157,8 @@ export type DefinedCreateInfiniteQueryResult< TData, TError >, -> =BaseQueryNarrowing & - MapToSignals +> = BaseQueryNarrowing & + MapToSignals export interface CreateMutationOptions< TData = unknown, From 428aa7f1956b2f23d6f872881c8b6367c9481697 Mon Sep 17 00:00:00 2001 From: mdm317 Date: Fri, 19 Sep 2025 00:42:05 +0900 Subject: [PATCH 3/5] fix: change to omit and fix function overload err --- .../src/inject-infinite-query.ts | 2 +- packages/angular-query-experimental/src/types.ts | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/angular-query-experimental/src/inject-infinite-query.ts b/packages/angular-query-experimental/src/inject-infinite-query.ts index 6df26a0bb5..4dbf2a80a6 100644 --- a/packages/angular-query-experimental/src/inject-infinite-query.ts +++ b/packages/angular-query-experimental/src/inject-infinite-query.ts @@ -125,5 +125,5 @@ export function injectInfiniteQuery( injectInfiniteQueryFn, InfiniteQueryObserver as typeof QueryObserver, ), - ) + ) as unknown as CreateInfiniteQueryResult } diff --git a/packages/angular-query-experimental/src/types.ts b/packages/angular-query-experimental/src/types.ts index a41f24625c..d0901185ce 100644 --- a/packages/angular-query-experimental/src/types.ts +++ b/packages/angular-query-experimental/src/types.ts @@ -144,8 +144,9 @@ export type DefinedCreateQueryResult< export type CreateInfiniteQueryResult< TData = unknown, TError = DefaultError, + TState = InfiniteQueryObserverResult, > = BaseQueryNarrowing & - MapToSignals> + MapToSignals> /** * @public @@ -153,12 +154,9 @@ export type CreateInfiniteQueryResult< export type DefinedCreateInfiniteQueryResult< TData = unknown, TError = DefaultError, - TDefinedInfiniteQueryObserver = DefinedInfiniteQueryObserverResult< - TData, - TError - >, + TState = DefinedInfiniteQueryObserverResult, > = BaseQueryNarrowing & - MapToSignals + MapToSignals> export interface CreateMutationOptions< TData = unknown, From c85e58aabcdf9f0b8726a6ea3799840d9e87b09d Mon Sep 17 00:00:00 2001 From: mdm317 Date: Sat, 20 Sep 2025 01:58:09 +0900 Subject: [PATCH 4/5] fix: propagate narrowing type to all query results --- .../src/__tests__/inject-query.test-d.ts | 10 +++++ .../src/inject-query.ts | 2 +- .../angular-query-experimental/src/types.ts | 40 +++++++++++++------ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts b/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts index 541ad65f14..a4aa1858d6 100644 --- a/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts +++ b/packages/angular-query-experimental/src/__tests__/inject-query.test-d.ts @@ -105,6 +105,16 @@ describe('initialData', () => { expectTypeOf(query.data).toEqualTypeOf>() } }) + it('error should be defined when query is error', () => { + const query = injectQuery(() => ({ + queryKey: ['key'], + queryFn: () => ({ wow: true }), + initialData: { wow: true }, + })) + if (query.isError()) { + expectTypeOf(query.error).toEqualTypeOf>() + } + }) }) describe('structuralSharing', () => { diff --git a/packages/angular-query-experimental/src/inject-query.ts b/packages/angular-query-experimental/src/inject-query.ts index 0defdf18e9..762f766383 100644 --- a/packages/angular-query-experimental/src/inject-query.ts +++ b/packages/angular-query-experimental/src/inject-query.ts @@ -226,5 +226,5 @@ export function injectQuery( !options?.injector && assertInInjectionContext(injectQuery) return runInInjectionContext(options?.injector ?? inject(Injector), () => createBaseQuery(injectQueryFn, QueryObserver), - ) as unknown as CreateQueryResult + ) as unknown as CreateQueryResult | DefinedCreateQueryResult } diff --git a/packages/angular-query-experimental/src/types.ts b/packages/angular-query-experimental/src/types.ts index d0901185ce..b9e26c98e8 100644 --- a/packages/angular-query-experimental/src/types.ts +++ b/packages/angular-query-experimental/src/types.ts @@ -61,32 +61,48 @@ type CreateStatusBasedQueryResult< TStatus extends QueryObserverResult['status'], TData = unknown, TError = DefaultError, -> = Extract, { status: TStatus }> + TState = QueryObserverResult, +> = Extract + +type CreateNarrowQueryResult< + TData = unknown, + TError = DefaultError, + TState = QueryObserverResult, + TNarrowState = TState, +> = BaseQueryNarrowing & + MapToSignals> /** * @public */ -export interface BaseQueryNarrowing { +export interface BaseQueryNarrowing< + TData = unknown, + TError = DefaultError, + TState = QueryObserverResult, +> { isSuccess: ( this: CreateBaseQueryResult, - ) => this is CreateBaseQueryResult< + ) => this is CreateNarrowQueryResult< TData, TError, - CreateStatusBasedQueryResult<'success', TData, TError> + TState, + CreateStatusBasedQueryResult<'success', TData, TError, TState> > isError: ( this: CreateBaseQueryResult, - ) => this is CreateBaseQueryResult< + ) => this is CreateNarrowQueryResult< TData, TError, - CreateStatusBasedQueryResult<'error', TData, TError> + TState, + CreateStatusBasedQueryResult<'error', TData, TError, TState> > isPending: ( this: CreateBaseQueryResult, - ) => this is CreateBaseQueryResult< + ) => this is CreateNarrowQueryResult< TData, TError, - CreateStatusBasedQueryResult<'pending', TData, TError> + TState, + CreateStatusBasedQueryResult<'pending', TData, TError, TState> > } @@ -117,7 +133,7 @@ export type CreateBaseQueryResult< TData = unknown, TError = DefaultError, TState = QueryObserverResult, -> = BaseQueryNarrowing & +> = BaseQueryNarrowing & MapToSignals> /** @@ -135,7 +151,7 @@ export type DefinedCreateQueryResult< TData = unknown, TError = DefaultError, TState = DefinedQueryObserverResult, -> = BaseQueryNarrowing & +> = BaseQueryNarrowing & MapToSignals> /** @@ -145,7 +161,7 @@ export type CreateInfiniteQueryResult< TData = unknown, TError = DefaultError, TState = InfiniteQueryObserverResult, -> = BaseQueryNarrowing & +> = BaseQueryNarrowing & MapToSignals> /** @@ -155,7 +171,7 @@ export type DefinedCreateInfiniteQueryResult< TData = unknown, TError = DefaultError, TState = DefinedInfiniteQueryObserverResult, -> = BaseQueryNarrowing & +> = BaseQueryNarrowing & MapToSignals> export interface CreateMutationOptions< From 29a7076a4c584b2870289b0185c935742d1bf182 Mon Sep 17 00:00:00 2001 From: Arnoud de Vries <6420061+arnoud-dv@users.noreply.github.com> Date: Sun, 21 Sep 2025 02:52:02 +0200 Subject: [PATCH 5/5] fix example type error --- .../src/app/components/example.component.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/angular/infinite-query-with-max-pages/src/app/components/example.component.html b/examples/angular/infinite-query-with-max-pages/src/app/components/example.component.html index 7afc85afe2..09a8a6c7ef 100644 --- a/examples/angular/infinite-query-with-max-pages/src/app/components/example.component.html +++ b/examples/angular/infinite-query-with-max-pages/src/app/components/example.component.html @@ -4,9 +4,11 @@

4 projects per page

3 pages max

@if (query.isPending()) {

Loading...

- } @else if (query.isError()) { + } + @if (query.isError()) { Error: {{ query.error().message }} - } @else { + } + @if (query.isSuccess()) {