Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.
Sign upHttp ResponseType cannot be set #18586
Comments
|
A workaround:
|
|
@zaiddabaeen currently, this is by design. Typescript needs to be able to infer the Another workaround is: const options = {headers, params, responseType: 'text' as 'text'};
return this.http.get(url, options).share(); |
|
I understand, but I believe that's unintuitive and confusing to the developers. I don't recall I ever casted a string to a 'string' before. Enumerating and using types as suggested would sound to me as a cleaner solution. |
|
@zaiddabaeen the problem is for: const res = this.http.get(url, options);What is the type of In other words: const res = this.http.get(url, {responseType: 'text'});is not equivalent to const options = {responseType: 'text'};
const res = this.http.get(url, options);In the first one Typescript can infer that the type of I expect most cases where this is desired can be solved with the spread operator: // Some options we want to control dynamically.
const options = {headers: ..., params: ...};
const res = this.http.get(url, {...options, responseType: 'text'});This way Typescript can infer the return type based on the signature and the value of |
|
So instead we have to do workarounds to get the desired effect? That can't be the way to go about this. I've been screaming at my computer for quite a while over this now, I've got a service which wraps the |
|
@chrillewoodz The default is JSON however. Why are you casting it to |
|
@zaiddabaeen I'm not casting anything to json (as far as I'm aware). This is what I have:
Attempting to add |
|
Use |
I have already tried all of the above :| |
|
I also had this problem, but by removing the Eg this does not work and returns the error:
But this does work:
|
|
The only way I got it to work without error was using @roddy's example, and that's with inlined options... Angular v4.4.3 |
|
The generic MUST not be used when responseType is specified to something other than Take a look at how it is defined for the /**
* Construct a GET request which interprets the body as an `ArrayBuffer` and returns it.
*
* @return an `Observable` of the body as an `ArrayBuffer`.
*/
get(url: string, options: {
headers?: HttpHeaders;
observe?: 'body';
params?: HttpParams;
reportProgress?: boolean;
responseType: 'arraybuffer';
withCredentials?: boolean;
}): Observable<ArrayBuffer>;
/**
* Construct a GET request which interprets the body as a `Blob` and returns it.
*
* @return an `Observable` of the body as a `Blob`.
*/
get(url: string, options: {
headers?: HttpHeaders;
observe?: 'body';
params?: HttpParams;
reportProgress?: boolean;
responseType: 'blob';
withCredentials?: boolean;
}): Observable<Blob>;
/**
* Construct a GET request which interprets the body as text and returns it.
*
* @return an `Observable` of the body as a `string`.
*/
get(url: string, options: {
headers?: HttpHeaders;
observe?: 'body';
params?: HttpParams;
reportProgress?: boolean;
responseType: 'text';
withCredentials?: boolean;
}): Observable<string>;
/**
* Construct a GET request which interprets the body as JSON and returns it.
*
* @return an `Observable` of the body as an `Object`.
*/
get(url: string, options?: {
headers?: HttpHeaders;
observe?: 'body';
params?: HttpParams;
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
}): Observable<Object>;
/**
* Construct a GET request which interprets the body as JSON and returns it.
*
* @return an `Observable` of the body as type `T`.
*/
get<T>(url: string, options?: {
headers?: HttpHeaders;
observe?: 'body';
params?: HttpParams;
reportProgress?: boolean;
responseType?: 'json';
withCredentials?: boolean;
}): Observable<T>;This makes perfect sense since the type can only be something angular does not know statically when the responseType is |
|
@reppners Hi Stefan, thank you for the explanation above. However, no matter how I try I cannot make the new HttpClient to work in a service that I am using to intercept image urls in my app:
Neither |
|
@a-kolybelnikov You can use something like this in your case:
|
|
@btory thank you. I have tried and it won’t work. |
|
try this: .. , responseType: 'text' as 'json' |
|
thanks @rds-rafael , |
Modified option observe from 'response' to 'reponse' as 'response'. Static typing issues... see angular/angular#18586
* feat(ui, general): adapt backend behaviour for authentication service changing authentication.service and tests * fix(client authentication): POst Options modified Modified option observe from 'response' to 'reponse' as 'response'. Static typing issues... see angular/angular#18586
|
Closing, the solution is to pass a correctly typed argument. |
|
For blobs: |
|
So whoever won the argument to re-factor Http to HttpClient this way is just wrong. |
|
@chrillewoodz's solution worked for me While I find the workaround to this to only be a minor annoyance it was really furustring that it was so difficult to actually find this answer. It'd be nice if this was better documented or I suppose a more intuitive solution be reached. |
|
@nortain you definitely don't need either. this.httpClient.post(url, data, {responsesType: 'text'})will give you an The only time you should be passing a type parameter to an |
|
@alxhub Ah thank you, that makes more sense and I realize i hadn't tried dropping the as 'text' when removing the generic. Also knowing that the generic is intended for json responses only helps. I appreciate the follow up. |
|
@alxhub
only |
|
All feels very convoluted to me. I'd rather have different methods to call for different results rather than the inference which is currently being used. |
|
@Pastafarian I agree, in one case I see (with the same responseType option) that: return this.httpClient.request('post', '/login', options) Does work, this on the other hand does not: return this.httpClient.post('/login', options) Not sure I agree this httpclient is any easier or more intuitive than the previous incarnation. On the contrary it's clunky and relies on a lot of under the covers inference. |
|
Am I missing something here? I just encountered this error myself I expect responseType blob.
I receive type error but if I do
It works just fine. Am I wrong thinking this is ridiculous? Answer that this is by design is not really a good answer it looks like a poor design to me if I can create HttpRequest where that param works as expected I'd expect it to work the same everywhere. Taking that docs don't mention this hacky approach anywhere. Granted I am new to TypeScript but it just doesn't seem right I have to resolve to workarounds like this is this a TypeScript issue or Angular? |
HttpClient uses overloaded signatures in TypeScript to determine return types for HttpClient calls based on two pieces of information: what the response type from the server will be, and whether the caller is interested in events, the full response, or just the response body. Previously this was accomplished by specifying 'responseType' and 'observe' properties of the 'options' argument to HttpClient as string values. This has a few disadvantages: 1) String literal values default to the 'string' type if they're not passed directly to a function signature that will narrow them. 2) JSON values returned from the server are only cast to the expected type, an assumption which is not checked at runtime. This commit adds new options for specifying both 'responseType' and 'observe'. responseType: a new type HttpResponseType captures both the expected response type and a function which will assert that the type is correct at runtime. Type inference can be used to determine the response type from the function. The HttpResponseType class has static functions on it for the 4 expected response types. observe: HttpObserve has a similar object, which returns strings narrowed to the right type. Fixes angular#18586.
|
I've spent the better part of a day on trying to figure out why postman gave the correct response and http.get didn't. I thought using http:get might work, but it didn't. Eventually I found this thread, saw that I had to take the out and use responseType: 'text' as 'text' as roddy suggested back last September. Then I read to the end of the post and found that it is still a problem. I think this should be fixed, or at the very least documented because it's far from intuitive! |
|
Actually on a second thought after initial bafflement it does makes sense to me now as in |
|
What I did in case of
|
|
Working for me
|
|
adding the responseType: 'blob' implicitly changes the result to Observable / Obserrvable<HttpResponse> Not typing the httpClient.post or httpClient.get solves it for me
gives the error, but
works |
|
this issue is still happening in Angular 7.1 |
|
I eventually came up with this and though I could share it: // define this namespace somewhere
namespace ResponseType {
export const JSON = 'json' as 'json';
export const ArrayBuffer = 'arraybuffer' as 'arraybuffer';
export const Blob = 'blob' as 'blob';
export const Text = 'text' as 'text';
}// import the namespace above and use it like this
const reqOpts = {
params: params,
headers: headers,
responseType: ResponseType.JSON,
};
// no type error, the right signature is selected
const a = await this.http.get(url, reqOpts);
const b = await this.http.get<MyClass>(url, reqOpts);#18586 (comment) gave a good hint at how to implement this. This solution also work for the Unless I missed something, this could be implemented in Angular directly, isn't ? You would need to first put the following in the declaration declare module '@angular/common/http' {
export namespace HttpResponseType {
export const JSON: 'json';
export const ArrayBuffer: 'arraybuffer';
export const Blob: 'blob';
export const Text: 'text';
}
export declare type HttpObserve = 'body' | 'events' | 'response';
export namespace HttpObserve {
export const Body: 'body';
export const Events: 'events';
export const Response: 'response';
}
}Then implement it in export namespace HttpResponseType {
export const JSON: 'json' = 'json';
export const ArrayBuffer: 'arraybuffer' = 'arraybuffer';
export const Blob: 'blob' = 'blob';
export const Text: 'text' = 'text';
}
export type HttpObserve = 'body' | 'events' | 'response';
export namespace HttpObserve {
export const Body: 'body' = 'body';
export const Events: 'events' = 'events';
export const Response: 'response' = 'response';
}Finally the two namespaces should be properly exported all the way back to |
|
@rgoupil this is a cool idea! |
|
I had the same problem. After a half an hour of trying to implement some of the suggestions above I wen't ahead with the following (dirty but...): // I actually get the response type as a parameter to my function
const responseType = 'text';
const options = {
headers: new HttpHeaders()
};
// @ts-ignore
options['responseType'] = responseType;
this.http.get(url, options); |
|
I have to hack it with |
Source: angular/angular#18586
|
Cast the httpOptions variable to type Object:
as specified in the docs:https://angular.io/api/common/http/HttpClient#get |
|
Any news on this? I've been struggling with the same issue on HttpClient.post's options... |
|
Working with Angular 7 (8 not tested yet)
|
this solution works for me |


I'm submitting a...
Current behavior
Response type cannot be set for HttpClient methods.
Would show an error
Expected behavior
It is expected that the response type should be exported like
And one would be able to set it using this type. Otherwise the type cannot be changed.
Environment
Angular version: 4.1.1 and still there in 5.0.0-beta.2
as seen here: https://github.com/angular/angular/blob/master/packages/common/http/src/client.ts