[FIXED] error TS2345: Argument of type 'OperatorFunction<Object, Object>' is not assignable to parameter of type 'OperatorFunction

Issue

How can I solve this problem?

Angular CLI: 14.0.2
Node: 16.13.0
rxjs: 7.5.5
typescript: 4.7.4

My imports :

import { Observable, BehaviorSubject } from "rxjs";
import { first, catchError, tap } from "rxjs/operators";

Error on first(),

    login(
    email: Pick<User, "email">,
    password: Pick<User, "password">
  ): Observable<{
    token: string;
    userId: Pick<User, "id">;
  }> {
    return this.http
      .post(`${this.url}/login`, { email, password }, this.httpOptions)
      .pipe(
        first(),
        tap((tokenObject: { token: string; userId: Pick<User, "id"> }) => {
          this.userId = tokenObject.userId;
          localStorage.setItem("token", tokenObject.token);
          this.isUserLoggedIn$.next(true);
          this.router.navigate(["/"]);
        }),
        catchError(
          this.errorHandlerService.handlerError<{
            token: string;
            userId: Pick<User, "id">;
          }>("login")
        )
      );
  }

Solution

You need to specify the return type of post so that it matches the return type of the function.

return this.http.post<{
    token: string;
    userId: Pick<User, "id">;
  }>( ... )
  .pipe( ... )

The return types within the pipe can be inferred by the compiler, but there is no way to tell the return type of post without you explicitly stating it.

I’d suggest you make a type so the code isn’t so verbose

type TokenAndId = {
    token: string;
    userId: Pick<User, "id">;
  }
  login(
    email: Pick<User, 'email'>,
    password: Pick<User, 'password'>
  ): Observable<TokenAndId> {
    return this.http
      .post<TokenAndId>(
        `${this.url}/login`,
        { email, password },
        this.httpOptions
      )
      .pipe(
        first(),
        tap((tokenObject: TokenAndId) => {
          this.userId = tokenObject.userId;
          localStorage.setItem('token', tokenObject.token);
          this.isUserLoggedIn$.next(true);
          this.router.navigate(['/']);
        }),
        catchError(this.errorHandlerService.handlerError<TokenAndId>('login'))
      );
  }

Answered By – Chris Hamilton

Answer Checked By – Laura B. (Easybugfix Admin)

Leave a Reply

(*) Required, Your email will not be published