Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ <h3>4 projects per page</h3>
<h3>3 pages max</h3>
@if (query.isPending()) {
<p>Loading...</p>
} @else if (query.isError()) {
}
@if (query.isError()) {
<span>Error: {{ query.error().message }}</span>
} @else {
}
@if (query.isSuccess()) {
<div>
<button
(click)="query.fetchPreviousPage()"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<InfiniteData<string, unknown>>()
}
})

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<undefined>()
}
})

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<Error>()
}
})
})

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<InfiniteData<string, unknown>>()
}
})

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<InfiniteData<string, unknown>>()
}
})

if (query.isSuccess()) {
const data = query.data()
expectTypeOf(data).toEqualTypeOf<InfiniteData<string, unknown>>()
}
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<Error>()
}
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ describe('initialData', () => {
expectTypeOf(query.data).toEqualTypeOf<Signal<{ wow: boolean }>>()
}
})
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<Signal<Error>>()
}
})
})

describe('structuralSharing', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,5 @@ export function injectInfiniteQuery(
injectInfiniteQueryFn,
InfiniteQueryObserver as typeof QueryObserver,
),
)
) as unknown as CreateInfiniteQueryResult
}
2 changes: 1 addition & 1 deletion packages/angular-query-experimental/src/inject-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,5 +222,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
}
49 changes: 32 additions & 17 deletions packages/angular-query-experimental/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,29 +52,45 @@ type CreateStatusBasedQueryResult<
TStatus extends QueryObserverResult['status'],
TData = unknown,
TError = DefaultError,
> = Extract<QueryObserverResult<TData, TError>, { status: TStatus }>
TState = QueryObserverResult<TData, TError>,
> = Extract<TState, { status: TStatus }>

export interface BaseQueryNarrowing<TData = unknown, TError = DefaultError> {
type CreateNarrowQueryResult<
TData = unknown,
TError = DefaultError,
TState = QueryObserverResult<TData, TError>,
TNarrowState = TState,
> = BaseQueryNarrowing<TData, TError, TState> &
MapToSignals<OmitKeyof<TNarrowState, keyof BaseQueryNarrowing, 'safely'>>

export interface BaseQueryNarrowing<
TData = unknown,
TError = DefaultError,
TState = QueryObserverResult<TData, TError>,
> {
isSuccess: (
this: CreateBaseQueryResult<TData, TError>,
) => this is CreateBaseQueryResult<
) => this is CreateNarrowQueryResult<
TData,
TError,
CreateStatusBasedQueryResult<'success', TData, TError>
TState,
CreateStatusBasedQueryResult<'success', TData, TError, TState>
>
isError: (
this: CreateBaseQueryResult<TData, TError>,
) => this is CreateBaseQueryResult<
) => this is CreateNarrowQueryResult<
TData,
TError,
CreateStatusBasedQueryResult<'error', TData, TError>
TState,
CreateStatusBasedQueryResult<'error', TData, TError, TState>
>
isPending: (
this: CreateBaseQueryResult<TData, TError>,
) => this is CreateBaseQueryResult<
) => this is CreateNarrowQueryResult<
TData,
TError,
CreateStatusBasedQueryResult<'pending', TData, TError>
TState,
CreateStatusBasedQueryResult<'pending', TData, TError, TState>
>
}

Expand All @@ -99,7 +115,7 @@ export type CreateBaseQueryResult<
TData = unknown,
TError = DefaultError,
TState = QueryObserverResult<TData, TError>,
> = BaseQueryNarrowing<TData, TError> &
> = BaseQueryNarrowing<TData, TError, TState> &
MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, 'safely'>>

export type CreateQueryResult<
Expand All @@ -111,23 +127,22 @@ export type DefinedCreateQueryResult<
TData = unknown,
TError = DefaultError,
TState = DefinedQueryObserverResult<TData, TError>,
> = BaseQueryNarrowing<TData, TError> &
> = BaseQueryNarrowing<TData, TError, TState> &
MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, 'safely'>>

export type CreateInfiniteQueryResult<
TData = unknown,
TError = DefaultError,
> = BaseQueryNarrowing<TData, TError> &
MapToSignals<InfiniteQueryObserverResult<TData, TError>>
TState = InfiniteQueryObserverResult<TData, TError>,
> = BaseQueryNarrowing<TData, TError, TState> &
MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, 'safely'>>

export type DefinedCreateInfiniteQueryResult<
TData = unknown,
TError = DefaultError,
TDefinedInfiniteQueryObserver = DefinedInfiniteQueryObserverResult<
TData,
TError
>,
> = MapToSignals<TDefinedInfiniteQueryObserver>
TState = DefinedInfiniteQueryObserverResult<TData, TError>,
> = BaseQueryNarrowing<TData, TError, TState> &
MapToSignals<OmitKeyof<TState, keyof BaseQueryNarrowing, 'safely'>>

export interface CreateMutationOptions<
TData = unknown,
Expand Down