8

I have this code snippet:

SubmitTransaction(transNumber: string, transactionRequest: ITransactionRequestObj): Observable<TransactionResponse> {
    this.body =  JSON.stringify(transactionRequest);
    this.headers = new HttpHeaders().set('Content-Type', 'application/json');
    this.headers.append('Accept', 'application/json');
    this.options = new RequestOptions({headers: this.headers});
    return this.http.post<TransactionResponse>(this.baseUrl + '/transactions/' + transNumber + '/new',  this.body, this.options)
   .pipe(catchError((e) => this.errorHandler(e)));
  }

where all I did was upgrade my project from Angular 5 to Angular 6 and change .catch((e) => this.errorHandler(e)); to .pipe(catchError((e) => this.errorHandler(e))); . However, I am getting the following TypeScript error for this particular method.

Error:

[ts]
Type 'Observable<HttpEvent<TransactionResponse>>' is not assignable to type 'Observable<TransactionResponse>'.
  Type 'HttpEvent<TransactionResponse>' is not assignable to type 'TransactionResponse'.
    Type 'HttpSentEvent' is not assignable to type 'TransactionResponse'.
      Property '_transactionNumber' is missing in type 'HttpSentEvent'.

I'm not sure what I should do in this scenario. The code snippet above was working in Angular 5. What do I need to do to fix it for Angular 6?

EDIT:

errorHandler(error: HttpErrorResponse) {
      return throwError(error.message || 'Server Error');
  }

I have noticed if I don't use the HttpHeaders, it works:

SubmitTransaction(transNumber: string, transactionRequest: ITransactionRequestObj): Observable<TransactionResponse> {
    this.body =  JSON.stringify(transactionRequest);
    this.headers = new HttpHeaders().set('Content-Type', 'application/json');
    this.headers.append('Accept', 'application/json');
    this.options = new RequestOptions({headers: this.headers});
    return this.http.post<TransactionResponse>(this.baseUrl + '/transactions/' + transNumber + '/new',  transactionRequest)
    .pipe(catchError((e) => this.errorHandler(e)));
  }

However, I might need to use the HttpHeaders... what is the workaround in this scenario?

Euridice01
  • 2,510
  • 11
  • 44
  • 76
  • post your errorHandler code please – firegloves Aug 04 '18 at 16:42
  • @firegloves edited post. – Euridice01 Aug 04 '18 at 16:52
  • 1
    I think HttpHeaders is immutable, you should chain some set method toghere instead of append – firegloves Aug 04 '18 at 16:55
  • Using Angular 6 / RxJs 6, it is not necessary to use JSON.stringify() on the request body. Adding to the above response, headers are immutable, so every call to append returns a new instance of the headers object. Most the instances that you create within the function call are not really necessary. Is there a particular reason that you are doing this for? Are you trying to cache these variables for later use? – alexc Aug 08 '18 at 14:12

3 Answers3

1

HttpHeaders is an immutable data structure.

The method append returns a new instance of HttpHeaders rather than mutating the existing one, meaning you'll need to make a tiny change in your code.

// old
this.headers.append('Accept', 'application/json')

// new
this.headers = this.headers.append('Accept', 'application/json')

Even better, just do it all at once:

this.headers = new HttpHeaders()
  .set('Content-Type', 'application/json')
  .set('Accept', 'application/json')
Lazar Ljubenović
  • 18,976
  • 10
  • 56
  • 91
  • Thanks. However, I still get the same error. What about this: this.options = new RequestOptions({headers: this.headers}); ? Is this correct? It complains about having this.options added to the post – Euridice01 Aug 04 '18 at 17:34
0

Running this code snippet on Angular 6, RxJS 6 fires the request without the above error. It should provide you with the exact same outcome as your code above:

SubmitTransaction(transNumber: string, transactionRequest: TransactionRequest): Observable<TransactionResponse> {
    return this.http
      .post<TransactionResponse>(`/myurl/transactions/${transNumber}/new`, transactionRequest, { headers: new HttpHeaders()
          .set('Accept', 'application/json') })
      .pipe(
        catchError(error => throwError(error.message || 'Server Error'))
      );
  }

I've simplified the code to not create an instance RequestOptions, leaving this process up to HttpClient's post pre-processing flow which creates the instance for you based on the provided hash.

I've also removed the caching for the body, headers and options from your method call. Feel free to add them back with the extracted variables from the options hash declared in the post call, however, unless you aim to cache these variables, there really is no need to to this.

alexc
  • 208
  • 2
  • 11
0

you can pass options like this:

headers: HttpHeaders = new HttpHeaders({
        'Content-Type': 'application/json',
    })

this.http.post<TransactionResponse>(this.baseUrl + '/transactions/' + transNumber + '/new',  this.body, {headers: this.headers})
       .pipe(catchError((e) => this.errorHandler(e)));

(Or)

You can cast it. this.http.post returns Observable<HttpEvent>. cannot directly cast Observable<HttpEvent> to Observable.

this.http.post<TransactionResponse>(this.baseUrl + '/transactions/' + transNumber + '/new',  this.body, this.options)
   .pipe(catchError((e) => this.errorHandler(e))) as unknown as Observable<TransactionResponse>;
mebunnu
  • 115
  • 1
  • 10