query icon indicating copy to clipboard operation
query copied to clipboard

fix(angular-query): fix injectInfiniteQuery to narrow type

Open mdm317 opened this issue 3 months ago • 5 comments

  • 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 Omit

    Currently, BaseQueryNarrowing only works in injectQuery when initialData is 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.

mdm317 avatar Sep 14 '25 07:09 mdm317