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'
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),
});
✅ 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,
});
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: [] },
});
@for (p of productsResource.value().products; track p.id) {
...
}
Bonus: Cancellation
productsResource = rxResource<ProductsResponse, void>({
params: () => undefined,
stream: ({ abortSignal }) =>
this.http.get<ProductsResponse>('/api/products', { signal: abortSignal }),
defaultValue: { products: [] },
});
Final Thoughts
Angular 20 didn’t break rxResource — it finished it.
The rename from request → params enforces a Signal‑first, explicit async model.
— Cristian Sifuentes

Top comments (0)