angularangular-httpclient

How do I use angular http.post and change Type 'Observavble<unknown> to a typed response?


I keep getting confused about how to type my HttpResponse. I'm trying to match what my api is giving me back but my typescript help in vim keeps telling me:

typescript: Type 'Observable<unknown>' is not assignable to type 'Observable<string | HttpErrorResponse>'.
  Type 'unknown' is not assignable to type 'string | HttpErrorResponse'. [2322]

This is what my post looks like:

forgotPassword(args: {studentId: string, emailAddress: string}): RxObservable<HttpErrorResponse | string> {
  const body = {
    studentId: args.studentId,
    emailAddress: args.emailAddress
  }
    console.log("forgot password", body)

    return this.http
      .post<HttpErrorResponse | string>(
        `${this.nextApiEndpoint}Authentication/ForgotPassword`,
        body,
        {}
      )
      .pipe(
        switchMap((data: string) => data),
        catchError((err) => {
          return err;
        })
      );
  }

I'm trying to use switchMap to make sure the data piped out is string, but I really don't need that because that is what my http response is already, a string.


Solution

  • You can just remove the HttpErrorResponse from the post and let catchError contain the type HttpErrorResponse. Also since we are not calling another API call with the previous data I swapped the switchMap with a map.

    To sum it up, we don't need to add extra lines for HttpErrorResponse just the success return type is enough and typescript will allow this.

    import { HttpClient, HttpErrorResponse } from '@angular/common/http';
    import { Injectable } from '@angular/core';
    import { Observable, of } from 'rxjs';
    import { catchError, map } from 'rxjs/operators';
    
    @Injectable()
    export class TestService {
      nextApiEndpoint = 'google.com';
      constructor(private http: HttpClient) {}
    
      forgotPassword(args: {
        studentId: string;
        emailAddress: string;
      }): Observable<string> {
        const body = {
          studentId: args.studentId,
          emailAddress: args.emailAddress,
        };
        console.log('forgot password', body);
    
        return this.http
          .post<string>(
            `${this.nextApiEndpoint}Authentication/ForgotPassword`,
            body,
            {}
          )
          .pipe(
            catchError((err: HttpErrorResponse) => {
              throw 'error in source. Details: ' + err.message;
            }),
            map((data: string): string => data)
          );
      }
    }
    

    Stackblitz Demo with no compilation errors