Home > front end >  RxJs observable: transforming data into enum causes a type error
RxJs observable: transforming data into enum causes a type error

Time:10-22

I have an Angular 14 app and I'm using Angular's HttpClient to make a request to my backend.

However, I have a requirement to transform the incoming data from a value returned from the server to an enum value that is defined in my frontend.

To do this, I've wrote this code:

public getState(): Observable<AuthState> {
    return this.http.get<any>(apiPaths.auth.isAuthorized, { observe: 'response' })
    .pipe(
        map(resp => {
            if (resp.ok) {
                if (this.responseIsValid(resp.body)) {
                    return AuthState.Ok;
                } else {
                    return AuthState.NotAuthorized;
                }
            } else {
                return AuthState.NotAuthenticated;
            }
        })
    );
}

As you can see, I'm getting a value from the backend and mapping it to a value of the AuthState enum, which is defined as follows:

export enum AuthState {
    NotAuthenticated = 'NotAuthenticated',
    NotAuthorized = 'NotAuthorized',
    Ok = 'Ok',
    ConnectionError = 'ConnectionError'
}

This seems to work, but here comes the problem: I also need to catch errors, so I added the catchError opertator into the observable pipe, like this:

public getState(): Observable<AuthState> {
    return this.http.get<any>(apiPaths.auth.isAuthorized, { observe: 'response' })
    .pipe(
        map(resp => {
            if (resp.ok) {
                if (this.responseIsValid(resp.body)) {
                    return AuthState.Ok;
                } else {
                    return AuthState.NotAuthorized;
                }
            } else {
                return AuthState.NotAuthenticated;
            }
        }),
        catchError(err => {
            return AuthState.ConnectionError;
        })
    );
}

As soon as I do this, hoever, the code stops compiling. The compiler throws the following error:

Type 'Observable<string>' is not assignable to type 'Observable<AuthState>'.
Type 'string' is not assignable to type 'AuthState'

It's like adding the catchError operator makes the entire pipe return Observable<string> instead of Obsevable<AuthState>.

Why is this happening? Note that this only happens when using an enum, if I change it to use any other type it works.

CodePudding user response:

You need to return observable, so change the catchError block to:

import { of } from 'rxjs';

catchError(err => {
   return of(AuthState.ConnectionError);
})

CodePudding user response:

You should map response to always be of type AuthState, since AuthState.NotAuthorized (or any other enum value) is of type string. You could do it separately for each return, or map response one more time. Also in catch block you return string, whereas you should return Observable. This should fix it:

public getState(): Observable<AuthState> {
return this.http.get<any>(apiPaths.auth.isAuthorized, { observe: 'response' })
.pipe(
    map(resp => {
        if (resp.ok) {
            if (this.responseIsValid(resp.body)) {
                return AuthState.Ok;
            } else {
                return AuthState.NotAuthorized;
            }
        } else {
            return AuthState.NotAuthenticated;
        }
    }),
    map(resp => resp as AuthState),
    catchError(err => {
        return of(AuthState.ConnectionError as AuthState);
    })
);
}
  • Related