19

I have an abstract base class in Typescript that looks like this:

import {Http, Headers, Response} from 'angular2/http'; 
export abstract class SomeService {
    constructor(private http:Http) {}   

    protected post(path:string, data:Object) {
        let stringifiedData = JSON.stringify(data);
        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        headers.append('Accept', 'application/json');

        this.http.post(`http://api.example.com/${path}`, stringifiedData, { headers })
            .map(res => res.json())
            .subscribe(obj => console.log(obj));
    }
}

It works perfectly. However, the Typescript compiler is complaining about .map(res => res.json()). I keep getting this error:

ERROR in ./src/app/components/shared/something/some.abstract.service.ts
(13,29): error TS2339: Property 'json' does not exist on type '{}'.

I followed the examples in the angular 2 documentation, and it works. I'm just sick of staring at this error. Am I missing something?

isuruAb
  • 2,202
  • 5
  • 26
  • 39
drewwyatt
  • 5,989
  • 15
  • 60
  • 106
  • It looks to me like the response you get already is json data, so the json() call is superfluous. And that would make sense since you specify the accept header, where the example link does not. – Gimby Nov 25 '15 at 15:06
  • @Gimby ah - duh. You are probably right, I can probably drop that line altogether. *But...* the compiler wouldn't know that, right? Shouldn't Typescript still allow me to do this - since it doesn't know what the return data will look like? – drewwyatt Nov 25 '15 at 15:11
  • Frankly, I missed the typescript tag myself, I know little to nothing about that :) – Gimby Nov 25 '15 at 15:27
  • 4
    Use `.map((res: Response) => res.json())` – Eric Martinez Nov 25 '15 at 15:41

2 Answers2

24

To me this looks strange...

.map(res => (<Response>res).json())

I would do

.map((res: Response) => res.json())
Mackelito
  • 4,213
  • 5
  • 39
  • 78
  • 1
    It's been a while since i wrote this question. I definitely prefer this now as well. – drewwyatt Jun 21 '17 at 13:23
  • now since the `Response` class is deprecated, so can you please write this answer also in the context of `HttpResponse` class. Mere replacing won't work, so please! – Ankur Shah Nov 27 '17 at 12:53
  • "Response" is just a interface.. you can create you own "MyCustomThing" interface and use that.. you would still use it the same way. But keep in mind that the .json() is not needed if you use the newer "HttpClient" instead of "Http" – Mackelito Nov 27 '17 at 19:40
  • I refer to the comment of @Mackelito which is helpful for the newer versions of Angular: `.json()` is not needed when you use "HttpClient" instead of "Http" – Has Aug 23 '19 at 17:53
9

You can get rid of this error by type-assertion to Response:

.map((res: Response) => res.json())

http.post() will return a Observable<Response> on wich map will require an Object of type Response. I think that's a missing definition in the current TypeScript AngularJS .d.ts.

CoderPi
  • 12,985
  • 4
  • 34
  • 62
  • This may just be a bandaid - but at least the error is gone. Thank you! – drewwyatt Nov 25 '15 at 15:12
  • TypeScript thinks `res` is of type empty Object. What type should it be? – CoderPi Nov 25 '15 at 15:17
  • 1
    An [observable](https://angular.io/docs/ts/latest/api/core/Observable-class.html) - it's mentioned [here](https://angular.io/docs/ts/latest/api/http/Http-class.html) – drewwyatt Nov 25 '15 at 15:19
  • If it's `Response` you might want to cast it to `` istead of ``. The problem is, that TypeScript can't automaticly assume res is `Response` because the context in `map` is not specific enough – CoderPi Nov 25 '15 at 15:20
  • `Observable`? – CoderPi Nov 25 '15 at 15:21
  • So, weird... I really thought you had it with `Observable` (that looks like it would be more accurate, based on the docs), but actually just plain `Response` is what I needed. If you update your answer I'll mark it as accepted. – drewwyatt Nov 25 '15 at 15:44
  • OK, I also added some additional Information on why you are facing this Problem. – CoderPi Nov 25 '15 at 15:49
  • I have another Idea: maybe you are missing something on `import` - try `import * from 'angular2/http';` – CoderPi Nov 25 '15 at 15:54
  • 1
    prefer `as` syntax for assertion ... also don't call it casting https://basarat.gitbooks.io/typescript/content/docs/types/type-assertion.html. Nevertheless +1 – basarat Nov 26 '15 at 00:01
  • So `.map(res as Response => res).json())` would work? Sorry for calling it casting – CoderPi Nov 26 '15 at 00:07
  • actually this answer helped me http://stackoverflow.com/a/37725361/942317 – STEEL Apr 17 '17 at 11:25