Skip to content
Open
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
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 numberDiff line numberDiff 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 numberDiff line numberDiff 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 numberDiff line numberDiff 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 numberDiff line numberDiff 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