Rainysen
Rainysen

Reputation: 23

Angular - The type 'Observable<unknown>' is not assignable to type 'Observable<HttpEvent<any>>'

I just copied this code from a tutorial

    import { Injectable } from '@angular/core';
    import {
      HttpInterceptor,
      HttpRequest,
      HttpHandler,
      HttpEvent,
      HttpErrorResponse
    } from '@angular/common/http';
    import { Observable, throwError, BehaviorSubject } from 'rxjs';
    import { AuthService } from './shared/auth.service';
    import { catchError, switchMap } from 'rxjs/operators';
    import { LoginResponse } from './login-response.payload';

    @Injectable({
      providedIn: 'root'
    })
    export class TokenInterceptor implements HttpInterceptor {

    isTokenRefreshing = false;
    refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject(null);
    constructor(public authService: AuthService) { }

    intercept(req: HttpRequest<any>,
        next: HttpHandler): Observable<HttpEvent<any>> {
        if (this.authService['getJwtToken']()) {
            this.addToken(req, this.authService['getJwtToken']());
        }

        return next.handle(req).pipe(catchError(error => {
          if (error instanceof HttpErrorResponse && error.status === 403){
            return this.handleAuthErrors(req, next);
          } else {
            return throwError(error);
          }
        }))
    }
    private handleAuthErrors(req: HttpRequest<any>, next: HttpHandler) {
        if (!this.isTokenRefreshing) {
            this.isTokenRefreshing = true;
            this.refreshTokenSubject.next(null);

            return this.authService['refreshToken']().pipe(
                switchMap((refreshTokenResponse: LoginResponse) => {
                    this.isTokenRefreshing = false;
                    
    this.refreshTokenSubject.next(refreshTokenResponse.authenticationToken);
                    return next.handle(this.addToken(req, 
    refreshTokenResponse.authenticationToken));
                })
            )
        }
    }
    private addToken(req: HttpRequest<any>, jwtToken: string) {
        return req.clone({
            headers: req.headers.set('Authorization',
                'Bearer ' + jwtToken)
            });
        }

    }

and i'm receiving this error

 'The type 'Observable<unknown>' is not assignable to type 
'Observable<HttpEvent<any>>
 Type 'unknown' is not assignable to type 'HttpEvent<any>'.

The error is caused here

    return next.handle(req).pipe(catchError(error => {
          if (error instanceof HttpErrorResponse && error.status === 404){
            return this.handleAuthErrors(req, next);
          } else {
            return throwError(error);
          }
        }))

What should I change to make it work?? (this the article btw https://programmingtechie.com/2020/04/05/build-a-full-stack-reddit-clone-with-spring-boot-and-angular-part-13/#Refresh_Token_Process_-_Step_by_Step)

Upvotes: 2

Views: 1228

Answers (3)

Noy Oliel
Noy Oliel

Reputation: 1666

I tried to analyze your code, however I was unable to understand the reason. If you are looking for a solution, you can add the return type Observable<HttpEvent<any>> to the function signature as follows:

private handleAuthErrors(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>

See the file check.js in a mock angular playground on stackblitz

This will solve your issue which comes from the usage of switchMap

see related post

Also, according to this, might be related to recent switch between rxjs versions. Try to restart IDE and clear cached node_modules

Upvotes: 1

Chris Hamilton
Chris Hamilton

Reputation: 10954

The compiler can't figure out the return type of handleAuthErrors because not all paths return a value. I don't know what the author intends to happen when the token is refreshing, but you can just return EMPTY.

  private handleAuthErrors(req: HttpRequest<any>, next: HttpHandler) {
    if (!this.isTokenRefreshing) { ... }
    return EMPTY;
  }

Upvotes: 1

Check out this similiar question:

There are two problems here, you need to typecast return to your output, also finalize is missing from imports.

Angular interceptor

I hope I could help you!

Kind regards Sebastian

Upvotes: 1

Related Questions