20

I am trying to change an existing app from using Http to using HttpClient, however i have an error.

So in my service now you can see the new code vs the old code that's been commented out:

constructor(
        // private http: Http
        private http: HttpClient
    ) { }

    getSidebar() {
        // return this.http.get('http://localhost:3000/sidebar/edit-sidebar')
        //     .map(res => res.json());
        return this.http.get('http://localhost:3000/sidebar/edit-sidebar');
    }

And in my page.component.ts I have this

this.sidebarService.getSidebar().subscribe(sidebar => {
                        this.sidebar = sidebar.content; // this does not work now
                    });

However for the line above which I commented on I get this error now:

Property 'content'
 does not exist on type 'Object'.

However if I console.log(sidebar) I get the following:

{_id: "59dde326c7590a27a033fdec", content: "<h1>sidebar here</h1>"}

So what's the issue?

Once again, Http works but HttpClient does not.

Kirk Larkin
  • 60,745
  • 11
  • 150
  • 162
Vojislav Kovacevic
  • 965
  • 2
  • 12
  • 27

6 Answers6

29

You can specify the type that is being returned, using an interface, class, etc. For example, you can use something like the following:

return this.http.get<Sidebar>('http://localhost:3000/sidebar/edit-sidebar');

As an example, Sidebar might be defined as:

interface Sidebar {
    _id: string;
    content: string;
}

See Typechecking the response from the Angular docs for further information:

...TypeScript would correctly complain that the Object coming back from HTTP does not have a results property. That's because while HttpClient parsed the JSON response into an Object, it doesn't know what shape that object is.

Kirk Larkin
  • 60,745
  • 11
  • 150
  • 162
18

HttpClient parse automatically the JSON response to an Object and the shape of that object is not known, that's why Typescript show this error

alternative solution, using bracket notation:

this.sidebarService.getSidebar().subscribe(sidebar => {
 this.sidebar = sidebar["content"];
});
Fateh Mohamed
  • 16,066
  • 4
  • 32
  • 45
15

You can assign the variable(sidebar) an interface to explicitely tell what it will get or assign to it so it doesnt throw compile time error.

this.sidebarService.getSidebar().subscribe((sidebar: any) => {
                        this.sidebar = sidebar.content; 
                    });
10

you can do this like that with type <any>

if you do this you will not get that error

this.http.get<any>('http://localhost:3000/sidebar/edit-sidebar');
Cenk YAGMUR
  • 2,036
  • 2
  • 18
  • 33
3

Using bracket notation instead of dot notation to reference sidebar['content'] instead of sidebar.content will solve the issue.

The Type-checking the response section of the Angular docs on HttpClient mention's this, although it's not all that clear:

The subscribe callback above requires bracket notation to extract the data values. You can't write data.heroesUrl because TypeScript correctly complains that the data object from the service does not have a heroesUrl property.

Kevin Leary
  • 6,842
  • 1
  • 47
  • 42
  • This is very helpful, some APIs do not conform to the type-checking that Angular wants by default with camelCase so this is helpful. –  Aug 16 '19 at 03:33
0

Error Description

ERROR in src/app/home.component.ts(131,20): error TS2339: Property 'someProperty' does not exist on type '{}'.

why Occured ?

I think this error is in service file , whenever you making http call and that call returns any Object(json) or array of Objects (json) , then yours http call should return Observable or Model of that result type

Home.service.ts

   connectToServer(data)  {
        return this.http.post('http://localhost:5000/connect' , data)
    }

Suppose , I have above Post http call , where i connect to server by passing data inside 'data' and this request returns me connection Object (Json).But where u seen that i didn't specify observable or model for holding result and if i access the result Object properties from component.ts it will says result.somepropery does not exist on {} .

Solutions

First :

connectToServer(data) : Observable<any> {
            return this.http.post('http://localhost:5000/connect' , data)
        }

Note : Don't forget to import Observable

Second :

  connectToServer(data) :  <Connection> {
                return this.http.post('http://localhost:5000/connect' , data)
            }

In second case you need to define Interface for declaring Connection Object fields and needs to import here.

Bhagvat Lande
  • 956
  • 2
  • 12
  • 28