From 84f397c831dd7cd3f8b20eac21e59afa7d7a4367 Mon Sep 17 00:00:00 2001 From: Matthieu Riegler Date: Tue, 17 Jun 2025 18:34:55 -0700 Subject: [PATCH] refactor(core): Support Error like object for on resource errors. Error like object will be treated as errors. Related to #61861 (cherry picked from commit 835a6431619360ffbeb91c4496896b8bf1d69074) --- .../rxjs-interop/test/rx_resource_spec.ts | 27 ++++++++++++++++++- packages/core/src/resource/resource.ts | 11 +++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/packages/core/rxjs-interop/test/rx_resource_spec.ts b/packages/core/rxjs-interop/test/rx_resource_spec.ts index 6cb4d36b66e..3bfae094a48 100644 --- a/packages/core/rxjs-interop/test/rx_resource_spec.ts +++ b/packages/core/rxjs-interop/test/rx_resource_spec.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import {of, Observable, BehaviorSubject} from 'rxjs'; +import {of, Observable, BehaviorSubject, throwError} from 'rxjs'; import {TestBed} from '../../testing'; import {ApplicationRef, Injector, signal} from '../../src/core'; import {rxResource} from '../src'; @@ -88,6 +88,31 @@ describe('rxResource()', () => { }); await appRef.whenStable(); }); + + it('should handle Error like objects', async () => { + class FooError implements Error { + name = 'FooError'; + message = 'This is a FooError'; + } + + const injector = TestBed.inject(Injector); + const appRef = TestBed.inject(ApplicationRef); + + const sig = signal(1); + const observable = throwError(() => new FooError()); + + const rxRes = rxResource({ + params: sig, + stream: () => observable, + injector: injector, + }); + + await appRef.whenStable(); + + expect(rxRes.error()).toBeInstanceOf(FooError); + + expect(() => rxRes.value()).toThrowError(/This is a FooError/); + }); }); async function waitFor(fn: () => boolean): Promise { diff --git a/packages/core/src/resource/resource.ts b/packages/core/src/resource/resource.ts index 1ed4cafce0f..80974086319 100644 --- a/packages/core/src/resource/resource.ts +++ b/packages/core/src/resource/resource.ts @@ -493,13 +493,22 @@ function createDebugNameObject( } export function encapsulateResourceError(error: unknown): Error { - if (error instanceof Error) { + if (isErrorLike(error)) { return error; } return new ResourceWrappedError(error); } +export function isErrorLike(error: unknown): error is Error { + return ( + error instanceof Error || + (typeof error === 'object' && + typeof (error as Error).name === 'string' && + typeof (error as Error).message === 'string') + ); +} + class ResourceValueError extends Error { constructor(error: Error) { super(