fix(angular-query): fix injectInfiniteQuery to narrow type
- fixes: #8984
- related: #9016
Cause
When using Omit, a union type is transformed into an object.
This causes BaseQueryNarrowing to behave unexpectedly and fail to narrow types correctly.
I believe this comment is related to the similar issue.
Problem
-
Using
OmitCurrently,
BaseQueryNarrowingonly works ininjectQuerywheninitialDatais not present. Repro example. -
Without
Omit
The narrowing works (see: #9016),
but then isSuccess becomes a strange intersection type:
((this: CreateBaseQueryResult) => this is CreateBaseQueryResult) & (() => false) & ...
As coderrabbitai pointed out, this can cause potential issues.
-
Using
DistributiveOmit
As suggested in a previous comment, using DistributiveOmit resolves the narrowing issue. However, it changes the inferred type of data as follows:
const { data } = injectQuery(() => ({
queryKey: ['key'],
queryFn: () => ({ wow: true }),
}))
// before
expectTypeOf(data).toEqualTypeOf<Signal<{ wow: boolean | undefined }>>()
// after (with DistributiveOmit)
expectTypeOf(data).toEqualTypeOf<Signal<{ wow: boolean }> | Signal<undefined>>()
I am not very familiar with Angular conventions, so I am not sure whether
Signal<{ wow: boolean }> | Signal<undefined> is considered valid.
This Pr
Fix BaseQueryNarrowing to narrow based on the data provided at the call site
I think we can use DistributiveOmit if Signal<{ wow: boolean }> | Signal<undefined> is considered an acceptable type in Angular, without changing the existing BaseQueryNarrowing behavior.
Let me know your thoughts.
Summary by CodeRabbit
-
New Features
- More precise TypeScript typings for query and infinite query results, improving type narrowing for success, error, and pending states.
- injectQuery/injectInfiniteQuery now expose broader, more accurate return types for better DX.
-
Examples
- Infinite query example updated to clearly separate loading, error, and success UI states.
-
Tests
- Expanded coverage for initialData scenarios and error typing, including status-guarded assertions.
-
Refactor
- Generalized internal typing to consistently carry state across result types, enhancing status-guard behavior without changing the public API.