DEV Community

Cristian Sifuentes
Cristian Sifuentes

Posted on

Angular rxResource Migration Guide — Fixing the `request` Error (Angular 20+)

Angular rxResource Migration Guide — Fixing the  raw `request` endraw  Error (Angular 20+)

Angular rxResource Migration Guide — Fixing the request Error (Angular 20+)

If you’ve recently upgraded to Angular 20+ and suddenly hit this error:

No overload matches this call.
Object literal may only specify known properties, and 'request' does not exist in type 'RxResourceOptions'
Enter fullscreen mode Exit fullscreen mode

Relax — nothing is broken.

You’ve just encountered a deliberate API evolution in Angular’s Resource system.

This post is a production‑minded guide to understanding why this error happens, what changed, and how to migrate cleanly — without fighting TypeScript.


TL;DR

Angular renamed Resource options:

Old (≤ v19) New (v20+)
request params
loader stream

If you still use request, TypeScript will fail by design.


Why This Change Happened

Angular’s Resource API matured alongside Signals-first architecture.

The new names reflect intent more clearly:

  • params → declarative reactive inputs
  • stream → explicit async producer
  • Stronger typing & cancellation
  • Clear separation between state and side effects

❌ Before (Old API — Angular ≤19)

rxResource({
  request: () => ({ id: this.id() }),
  loader: ({ request }) => this.api.getById(request.id),
});
Enter fullscreen mode Exit fullscreen mode

✅ After (New API — Angular 20+)

import { rxResource } from '@angular/core/rxjs-interop';

type Params = { id: string };
type Result = Product;

productResource = rxResource<Result, Params>({
  params: () => ({ id: this.id() }),
  stream: ({ params }) => this.api.getById(params().id),
  defaultValue: {} as Result,
});
Enter fullscreen mode Exit fullscreen mode

Key Detail

params is a Signal, so you must read it as params().


Fixing Template Errors (.products, .images)

type ProductsResponse = { products: Product[] };

productsResource = rxResource<ProductsResponse, void>({
  params: () => undefined,
  stream: () => this.http.get<ProductsResponse>('/api/products'),
  defaultValue: { products: [] },
});
Enter fullscreen mode Exit fullscreen mode
@for (p of productsResource.value().products; track p.id) {
  ...
}
Enter fullscreen mode Exit fullscreen mode

Bonus: Cancellation

productsResource = rxResource<ProductsResponse, void>({
  params: () => undefined,
  stream: ({ abortSignal }) =>
    this.http.get<ProductsResponse>('/api/products', { signal: abortSignal }),
  defaultValue: { products: [] },
});
Enter fullscreen mode Exit fullscreen mode

Final Thoughts

Angular 20 didn’t break rxResource — it finished it.

The rename from requestparams enforces a Signal‑first, explicit async model.

Cristian Sifuentes

Top comments (0)