Search code examples
angulartypescripttypescript-typingsrxjs6

How do I use catchError() and still return a typed Observable with rxJs 6.0?


cdSo I'm trying to migrate some of my Angular 5 code to 6, and I understand most of the changes required for rxjs to work using the .pipe() operator. It works as you would expect for 'pipable' operations.

However, the behavior of catchError() is different than the .catch() operator. Prior to rxjs 6 I used the .catch() operator to transform the error input into a a consistent error object that can then be caught in the `.subscribe().

getAlbums(): Observable<Album[]> {
     return this.httpClient.get<Album[]>(this.config.urls.url("albums"))
           .map(albumList => this.albumList = albumList)
           .catch(new ErrorInfo().parseObservableResponseError);            
    }

new ErrorInfo().parseObservableResponseError is a function that takes a error object as input and parses the input error into a simpler error object with a normalized object. Catch returns Observable<any>:

parseObservableResponseError(response): Observable<any> {
    let err = new ErrorInfo();
    ...
    return Observable.throw(err);        
}

This worked great for easily handling errors up rxjs5 - errors basically are captured as part of the pipeline and then throw a well known error structure that can be captured .subscribe() error function.

Moving that same code to rxjs 6 however and using .pipe() I am trying to do the following:

getAlbums(): Observable<Album[]> {
    return this.httpClient.get<Album[]>(this.config.urls.url("albums"))
                .pipe(
                    map(albumList => this.albumList = albumList),
                    catchError(new ErrorInfo().parseObservableResponseError)                        
                );           
}

However this doesn't work because catchError now returns a result of Observable<any> into the pipeline, which is not what I want here. In essence I just want to re-throw any errors as I did before.

error TS2322: Type 'Observable<{} | Album[]>' is not assignable to type 'Observable'

How do simulate the old operator .catch()behavior?

Update:

After mucking around with this a bit more, the code as shown just started working without giving me a build error. Honestly I have no idea why it failed with the error message before, but is working now. The suggestion by @cartant in the comments is an explicit way to specify the result and that works as well.


Solution

  • You should be able to explicitly specify the type parameters to catchError to indicate that it won't return an observable that emits a value - that is, it will return Observable<never> - and will always throw:

    getAlbums(): Observable<Album[]> {
        return this.httpClient.get<Album[]>(this.config.urls.url("albums"))
            .pipe(
                map(albumList => this.albumList = albumList),
                catchError<Album[], never>(new ErrorInfo().parseObservableResponseError)
            );           
    }
    

    Doing so will see the type inferred from the pipe call to be Observable<Album[]>.