'Angular 12 - Error : No overload matches this call. Overload 1 of 5

The following is my code:

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  isAuth$ = new BehaviorSubject<boolean>(false);
  token!: string ; 
  userId!: string;

  constructor(private router: Router,
    private http: HttpClient) { }


  createNewUser(email: string, password: string) {
    return new Promise<void>((resolve, reject) => {
      this.http.post(
        'http://localhost:3000/api/auth/signup',
        { email: email, password: password })
        .subscribe(
          () => {
            this.login(email, password).then(
              () => {
                resolve();
              }
            ).catch(
              (error) => {
                reject(error);
              }
            );
          },
          (error) => {
            reject(error);
          }
        );
    });
  }

  login(email: string, password: string) {
    return new Promise<void>((resolve, reject) => {
      this.http.post(
        'http://localhost:3000/api/auth/login',
        { email: email, password: password })
        .subscribe(
          (authData: { token: string, userId: string }) => {  //====> Error 
            this.token = authData.token;
            this.userId = authData.userId;
            this.isAuth$.next(true);
            resolve();
          },
          (error) => {
            reject(error);
          }
        );
    });
  }

  logout() {
    this.isAuth$.next(false);
    this.userId = null!;
    this.token = null!;
  }
}

Error description:

No overload matches this call. Overload 1 of 5, '(next: null, error: (error: any) => void, complete?: () => void): Subscription', gave the following error. Argument of type '(authData: { token: string; userId: string;}) => void' is not assignable to parameter of type 'null'.
Overload 2 of 5, '(next?: (value: Object) => void, error?: (error: any) => void, complete?: () => void): Subscription', gave the following error. Argument of type '(authData: { token: string; userId: string;}) => void' is not assignable to parameter of type '(value: Object) => void'. Types of parameters 'authData' and 'value' are incompatible. The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead? Type 'Object' is missing the following properties from type '{ token: string; userId: string; }': token, userId

The following is my code

Error description



Solution 1:[1]

You have to specify the response data type that is expected to receive for this.http.post.

Solution 1: Specify as { token: string, userId: string } type

login(email: string, password: string) {
    return new Promise<void>((resolve, reject) => {
      this.http.post<{ token: string, userId: string }>(
        'http://localhost:3000/api/auth/login',
        { email: email, password: password })
        .subscribe(
          (authData: { token: string, userId: string }) => { 
            this.token = authData.token;
            this.userId = authData.userId;
            this.isAuth$.next(true);
            resolve();
          },
          (error) => {
            reject(error);
          }
        );
    });
  }

Solution 2: Specify as any type

login(email: string, password: string) {
    return new Promise<void>((resolve, reject) => {
      this.http.post<any>(
        'http://localhost:3000/api/auth/login',
        { email: email, password: password })
        .subscribe(
          (authData: { token: string, userId: string }) => { 
            this.token = authData.token;
            this.userId = authData.userId;
            this.isAuth$.next(true);
            resolve();
          },
          (error) => {
            reject(error);
          }
        );
    });
  }

Solution 2:[2]

You can change the generic type of this.http.post function to be { token: string, userId: string } like the following:

this.http.post<{ token: string, userId: string }>(......);

However, I think it's better in your case to use Observable directly without promise, and without subscription within your function.

You can achieve that like the following:

  login(email: string, password: string): Observable<void> {
    return this.http
      .post<{ token: string; userId: string }>(
        "http://localhost:3000/api/auth/login",
        {
          email: email,
          password: password,
        }
      )
      .pipe(
        map((authData) => {
          this.token = authData.token;
          this.userId = authData.userId;
          this.isAuth$.next(true);
        })
      );
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Yong Shun
Solution 2 Amer