Skip to content

fix(router): expose a public RouteResource<T> type for route resources with reload() #71299

Open

Description

@lacolaco

Which @angular/* package(s) are relevant/related to the feature request?

router

Description

When a route resource is wrapped with nonBlocking() and withComponentInputBinding() is enabled, the component input receives the router-wrapped resource itself. At runtime this object is the result of routerResource(), typed internally as Resource<T> & {reload(): boolean}, so calling reload() on it is supported.

However, there is no public named type for this object. Resource<T> has no reload(), and WritableResource<T> / ResourceRef<T> expose set, update, and destroy, which the router-wrapped resource does not implement. As a result, users have to define their own type to declare the input:

type RouteResource<T> = Resource<T> & { reload(): boolean };

export class UserList {
  readonly usersResource = input.required<RouteResource<User[] | undefined>>();

  async save() {
    // ...
    this.usersResource().reload();
  }
}

#70702 (fixing #70698) addressed the same gap for ActivatedRoute.resources by changing ResourceResult to Record<string, Resource<unknown> & Pick<WritableResource<unknown>, 'reload'>>. The value type there is still an anonymous intersection, so it cannot be reused generically for component inputs. During the review of #70702, an intermediate ReloadableResource type was mentioned as an option, but it was not added.

Proposed solution

Export a named generic type that describes what the router actually provides, and use it in the router's public API:

export type RouteResource<T> = Resource<T> & Pick<WritableResource<T>, 'reload'>;
export type ResourceResult = Record<string, RouteResource<unknown>>;

The name follows the "route resources" terminology used throughout the routing guide and matches Route.resources.

Alternatively, if the team prefers a framework-wide type, a ReloadableResource<T> in @angular/core (as suggested in the #70702 review) would serve the same purpose, and the router could reference it.

Either way, the data fetching guide could then show the type for a nonBlocking resource input instead of Resource<T>.

Activity

  1. added this to the needsTriage milestone on Oct 11, 2026
  2. benjavicente commented on Oct 13, 2026

    @benjavicente

    Note that this will be also useful for signal forms: #69443

    In Angular TanStack Query, we are defining an type alias for it.

  3. syedryaaan commented on Oct 14, 2026

    @syedryaaan

    Hi @lacolaco, I’d love to contribute to this issue if it’s still available for implementation.

    I think introducing a public, generic RouteResource<T> would be a valuable improvement beyond this specific use case. Currently, consumers need to recreate the Resource<T> & { reload(): boolean } intersection themselves, even though this is already a meaningful part of the Router’s runtime API. Providing a named type would make component input declarations more discoverable, reusable, and consistent with the actual behavior of route resources.

    I also see the broader value mentioned in the discussion. This abstraction could be useful for Signal Forms (#69443) and other integrations that need a resource with reload support. Angular TanStack Query already defines a similar type alias in its [query-resource implementation](https://github.com/TanStack/query/blob/6404d77552c803102b39a0dcd0777ab3d131fefd/packages/angular-query/src/query-resource.ts#L6-L21), which highlights the value of having a clear, reusable type contract rather than requiring each integration to maintain its own equivalent.

    I’d be happy to investigate the existing ResourceResult and routerResource() definitions, evaluate whether RouteResource<T> belongs in @angular/router or whether a framework-wide ReloadableResource<T> would be more appropriate, and prepare a focused implementation with the necessary type tests and documentation updates.

    I’d also make sure the change preserves the existing public API and accurately reflects the capabilities exposed by the router-wrapped resource, without implying that it supports writable operations such as set() or update().

    I noticed that PR #71300 has already been opened for this issue, so I don’t want to duplicate work or conflict with the current implementation. Would you be open to me helping with additional type tests, documentation for nonBlocking() with withComponentInputBinding(), or another specific part of the change that would be useful to the team?

    I’d appreciate the opportunity to contribute and follow the direction preferred by the Angular maintainers. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions