Angular set null to User object on logout

Viewed 2875

I am trying to build a simple user authentication app in Angular following this tutorial. I am facing an error when I am trying to set null to the User object after the user has logged out.

Error:

ERROR in src/app/_services/authentication.service.ts(40,38): error TS2345: Argument of type 'null' is not assignable to parameter of type 'User'.

Relevant code (authentication.service.ts):

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {BehaviorSubject, Observable} from 'rxjs';
import {map} from 'rxjs/operators';

import {User} from '@/_models';
import { environment } from 'environments/environment';

@Injectable({providedIn: 'root'})
export class AuthenticationService{
    private currentUserSubject: BehaviorSubject<User>;
    public currentUser: Observable<User>;

    constructor(private http: HttpClient){
        this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser') || '{}'));
        this.currentUser = this.currentUserSubject.asObservable();
    }

    public get currentUserValue(): User{
        return this.currentUserSubject.value;
    }

    login(username: string, password: string){
        return this.http.post<any>(`${environment.apiUrl}/user/login/`, {username, password})
            .pipe(map(user => {
                console.log(user);
                // login successful if there is a jwt token in the response
                if(user.status && user.data.token){
                    // store user details and jwt token in local storage to keep user logged in 
                    // between page refreshes
                    localStorage.setItem('currentUser', JSON.stringify(user));
                    this.currentUserSubject.next(user);
                }
            }));
    }

    logout(){
        // remove user from local storage to log user out
        localStorage.removeItem('currentUser');
        this.currentUserSubject.next(null);
    }
}

I can solve the problem by setting "strict": false in tsconfig.json, but I want to follow the best practices. Any idea why this is happening and how to fix it?

Update: The User model is:

export class User {
    id!: number;
    username!: string;
    token?: string;
}
3 Answers

I just found a solution in case anyone else has this issue. I tried this and it is working in my application, and I did not disable strict checking.

  logout() {
     // remove user from local storage to log user out
     localStorage.removeItem('currentUser');

     // get the user nulled - typescript won't care
     this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser')!));
     this.currentUser = this.currentUserSubject.asObservable();
   }

the problem is in this line:

this.currentUserSubject = new BehaviorSubject<User>(JSON.parse(localStorage.getItem('currentUser') || '{}')

On constructor, You are setting value for currentUserSubject, but if there is no value for currentUser in your localStorage, then it will be initiated with null value.

Update

logout(){
    localStorage.clear();
    this.currentUserSubject = new BehaviorSubject<User>({});
}

Just for an suggestion let try this,

logout(){
        // remove user from local storage to log user out
        localStorage.removeItem('currentUser');
        this.currentUserSubject = new BehaviorSubject<User>();
    }

new keyword is used to initialize object. So the empty object is initialed.

Related