Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
The response body doesn't return all the data you may need. Sometimes
servers return special headers or status codes to indicate certain
conditions, and inspecting those can be necessary. To do this, you can
tell HttpClient you want the full response instead of just the body
with the observe option:
.get<MyJsonData>('/data.json', {observe: 'response'})
.subscribe(resp => {
// Here, resp is of type HttpResponse<MyJsonData>.
// You can inspect its headers:
console.log(resp.headers.get('X-Custom-Header'));
// And access the body directly, which is typed as MyJsonData as requested.
console.log(resp.body.someField);
But when I try that, I get a compilation time error (no runtime errors though, works as expected):
error TS2345: Argument of type '{ headers: HttpHeaders; observe: string; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'.
Types of property 'observe' are incompatible.
Type 'string' is not assignable to type '"body"'.
Why? I use
"@angular/http": "^5.1.0"
Here is my version of the code:
login(credentials: Credentials): Observable<any> {
const options = {
headers: new HttpHeaders({'Content-Type': 'application/json'}),
observe: 'response'
return this.httpClient.post<any>(`${environment.USER_SERVICE_BASE_URL}`,
{'username': credentials.username, 'password': credentials.password}, options)
.map((res) => ...
–
–
You have to inline the options. See github ticket #18586, entry by alxhub
on August 9
2017.
Typescript needs to be able to infer the observe and responseType values statically, in order to choose the correct return type for get(). If you pass in an improperly typed options object, it can't infer the right return type.
login(credentials: Credentials): Observable<any> {
return this.httpClient.post<any>(`${environment.USER_SERVICE_BASE_URL}`,
{'username': credentials.username, 'password': credentials.password}, {
headers: new HttpHeaders({'Content-Type': 'application/json'}),
observe: 'response'
.map((res) => ...
–
The way I got around this, without inline-ing the options (which can lead to code that's not as clean) was to create an interface for the request options. Code looks like this :
export interface IRequestOptions {
body?: any;
headers?: HttpHeaders | { [header: string]: string | Array<string> };
observe?: any;
params?: HttpParams | { [param: string]: string | Array<string> };
reportProgress?: boolean;
responseType?: "arraybuffer" | "blob" | "json" | "text";
withCredentials?: boolean;
Then this is used as such :
const options: IRequestOptions = {
headers: new HttpHeaders({"Content-Type": "application/json"}),
observe: "response"
return this.httpClient.post(`${environment.USER_SERVICE_BASE_URL}`,
{"username": credentials.username, "password": credentials.password}, options)
.pipe(
map((res: HttpResponse<any>) => ...
Change for original post to use lettable
or pipeable
(whatever the current name is today) operators
import { HttpHeaders, HttpParams } from '@angular/common/http';
export interface IRequestOptions {
headers?: HttpHeaders | { [header: string]: string | string[]; };
observe: "response";
params?: HttpParams | { [param: string]: string | string[]; };
reportProgress?: boolean;
responseType?: "json";
withCredentials?: boolean;
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.