36

I am unable to make a POST request in Angular 5 that accepts text/plain as response. Angular is calling a method which expects JSON as response and hence throws an error when response comes while trying to parse the response.

I tried calling method with parameter {responseType: 'text'} but VS code is showing it as an error and I am also getting an error in the console when the application is compiled.

Below is the Angular 5 code for a POST request that expects a response as text/plain.

this.http
.post<string>(this.loginUrl, this.user, {responseType: 'text'}) // error in this line
.subscribe(
    (data) => this.success(data),
    (error) => this.failure(error)
);

While compilation the following error show in the console:

ERROR in src/app/login/login.component.ts(47,47): error TS2345: Argument of type '{ responseType: "text"; }' is not assignable to parameter of type '{ headers?: HttpHeaders | { [header: string]: string | string[]; }; observe?: "body"; params?: Ht...'.
  Types of property 'responseType' are incompatible.
    Type '"text"' is not assignable to type '"json"'.

5 Answers 5

53

The version of post accepting responseType:'text' is not generic, since the result type is already clear (ie string)

this.http
.post(this.loginUrl, this.user, {responseType: 'text'}) // no generic parameter
.subscribe(
    (data) => this.success(data), // data is string
    (error) => this.failure(error)
);
3
  • I still do not understand what was causing this issue? Why by adding .post<string> could resolve to a conflict with reponseType: 'text' ?
    – Logan Wlv
    Commented Sep 14, 2018 at 13:20
  • 3
    @LoganWlv because there are multiple overloads, and the overload with responseType: 'text' is not generic, and the overload that is generic that is generic only allows 'json' for responseType Commented Sep 14, 2018 at 13:24
  • It's not working for me in Angular 9, here is what I had to do: stackoverflow.com/a/60693216/6410464
    – atb00ker
    Commented Mar 15, 2020 at 13:11
19

Here is an approach if you don't want to remove <string> to keep your response strongly typed:

    const httpOptions = {
      headers: new HttpHeaders({
        'Accept': 'text/plain, */*',
        'Content-Type': 'application/json' // We send JSON
      }),
      responseType: 'text' as 'json'  // We accept plain text as response.
    };
    return this.http.post<string>(this.setBaseUrl, body, httpOptions);

Replace text with valid responseType according the data that you want to receive.

4
  • 1
    I don't see how removing <string> is any more of a hack than setting the responseType to 'text' as 'json'. Is there any functional difference between the two?
    – Flaom
    Commented Mar 16, 2021 at 20:05
  • I don't think there should be a functional difference. The only reason I would call it a better approach is in typescript, explicit mention of datatype is preferred; which is not violated here.
    – atb00ker
    Commented Mar 20, 2021 at 10:37
  • Actually removing <string> is not a hack and doesn't go against the typescript approach. In fact, it is Angular's httpClient's implementation that decides that if you use the resposneType: 'text, it is unneccesary to provide a generic and hence this overloaded method doesn't even accept a generic type. If anything, telling typescript to treat 'text' as 'json' is definitely a hack.
    – Zabi Babar
    Commented May 10, 2021 at 18:17
  • 'text' as 'json' is type assertion. Since I am expecting to receive a json, I am just telling typescript to behave as if the result would be JSON, please google the keyword as. It's always preferred to keep things strongly typed where possible (please google the reasons for it). If you don't care about type, please use any (any is default; it's too permissive, allows anything to be done to the variable; not recommended when it's possible to avoid -- omitting type makes it any). I've removed the word hack as I don't have time to reply to more comments on it. Cheers.
    – atb00ker
    Commented May 13, 2021 at 14:41
15

Just remove "string" from your request. Try this:

this.http.post(this.loginUrl, this.user, {responseType: 'text'}).subscribe(
    (data) => this.success(data),
    (error) => this.failure(error)
);
1
  • This is only a hack. I don't know if at the time of asking the question a better solution was possible or not, but today certainly you can do stackoverflow.com/a/60693216/6410464
    – atb00ker
    Commented Mar 15, 2020 at 13:10
3

I just ran into this particular issue today myself. After searching for a little and figuring that the responseType option should exist, I managed to get it work as below:

let requestOptions: Object = { 
    headers: new HttpHeaders().set('Authorization', 'Basic ' + credentials),
    responseType: 'text'
}    

return this.httpClient.get<any>(
                this.environment.tokenHost + this.environment.authenticationURL,
                requestOptions
            )
            .subscribe(result => {
                // do stuff
            });

Setting the responseType like that makes it work, compared to configuring it in the 'request' itself.

Regards.

2
this.http.post(this.loginUrl,this.user,{headers:
new HttpHeaders({'content-type':'application/json'}), responseType:'text'})
.subscribe((r)=>{console.log(r)})

Edit

It is wierd but creating header object separately like below snippet

let headerOptions = {
 headers: new HttpHeaders(
     {'content-type':'application/json'}),
       responseType:'text'
 }
this.http.post(this.loginUrl,this.user, headerOptions)
 .subscribe((r)=>{console.log(r)})

would throw error in VS code, so the idea is to pass the entire object in inline post request like above would solve the compilation error.

3
  • Can you add description? Commented Mar 25, 2019 at 16:40
  • This fixed the issue for me, no idea why we can't create the header options separately for reusability etc. Inline only if you want to customize responseType Commented Oct 8, 2019 at 4:04
  • responseType: 'text' as 'text' works when you have a separate object. Give it a try. Commented Sep 3, 2021 at 11:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.