[SOLVED] Problem with accessing object properties

Hi,
I am going through an Angular project and I am meeting a problem I do not understand.
Basically I use the JSON Placeholder API to send a post on POST request.
My service indeed returns a response and I can log it successfully in the console.

The problem begins when I try to display any property from the response body.
It works on type. This is the only attribute VS Code finds.

Now I need to access status or headers/body content but it simply does not allow that. I do not understand what I would be doing wrong.

Here is the code for my service.

  httpPostOptions: any = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    }
    ),
    observe: 'response'
  };
// Some more code
  sendPostWithResponse(post: IPost): Observable<HttpEvent<HttpResponse<IPost>>> {
    return this.http.post<HttpResponse<IPost>>(this.completeUrl, post, this.httpPostOptions);
  }

Thanks in advance.

A temporary solution is to change the return type in my service to any.
It works but I wish to strongly type my return value and understand why it doesn’t the way I do.

sendPostWithResponseAny(post: IPost): Observable<any> {
   return this.http.post<HttpResponse<IPost>>(this.completeUrl, post, this.httpPostOptions);
}

OK I solved the problem myself.

The thing is the type I got came from I returned an HttpEvent type which only has a type property. The value 4 means it is an HttpResponse.

Though we can’t see it in the console, it went through other event types in the process. Eventually, it resolves to a response.

Watching events is the way to go should we need to track long processes (such as file upload). I didn’t do it myself but it seems there is a boolean reportProgress property to add in the HttpOptions to track progress. I don’t need that here.

The properties become available if we precise the type of event within the method body.

In further codes, the httpOptions have been changed to observe events

  httpPostOptions: any = {
    headers: new HttpHeaders({
      'Content-Type': 'application/json'
    }
    ),
    observe: 'events'
  };

There are 2 ways I did solve this.

1st way

Service

I wrap the return type into HttpResponse amongst others.

sendPostWithResponse(post: IPost): Observable<HttpEvent<HttpResponse<IPost>>> {
    return this.http.post<HttpResponse<IPost>>(this.completeUrl, post, this.httpPostOptions);
}

Controller

I need to cast to unknow and IPost for it to compile.

    this.postService.sendPostWithResponse(data).subscribe({
      next: (v) => {
        if (v.type === HttpEventType.Response) {
          let thisPost: IPost = v.body as unknown as IPost;

          let dataMsg = "Id: " + thisPost.id + "\n";
          dataMsg += "User Id: " + thisPost.userId + "\n";
          dataMsg += "Title: " + thisPost.title + "\n";
          dataMsg += "Body: " + thisPost.body + "\n";
          console.log("DATA SENT\n" + dataMsg)
          console.log(v);
          console.log(v.body)
        }
      },
      error: (e) => { console.log(e) },
      complete: () => { console.log('COMPLETE') },
    });
  }

2nd way preferred option IMHO

Service

I do not wrap my return type in HttpResponse. HttpEvent eventually returns the response

sendPostWithResponse(post: IPost): Observable<HttpEvent<IPost>> {
    return this.http.post<IPost>(this.completeUrl, post, this.httpPostOptions);
}

Controller

IMHO the code looks cleaner and I do not need a prior cast to unknown.

    this.postService.sendPostWithResponse(data).subscribe({
      next: (v) => {
        if (v.type === HttpEventType.Response) {
          let thisPost: IPost = v.body as IPost;

          let dataMsg = "Id: " + thisPost.id + "\n";
          dataMsg += "User Id: " + thisPost.userId + "\n";
          dataMsg += "Title: " + thisPost.title + "\n";
          dataMsg += "Body: " + thisPost.body + "\n";
          console.log("DATA SENT\n" + dataMsg)
          console.log(v);
          console.log(v.body)
        }
      },
      error: (e) => { console.log(e) },
      complete: () => { console.log('COMPLETE') },
    });
  }