Raj
Raj

Reputation: 43

Angular 5 Type 'Observable<{}>' is not assignable to type error while getting data from a API

i have a API which return JSON data of posts. I am trying to fetch these data from Angular 5 with this approach.

I declare a Post interface

export interface Post {
    userId:number;
    id:number;
    title:string;
    body:string
}

and my post.service.ts file

    import { Injectable } from '@angular/core';
    import {Post} from './post';
    import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { catchError, map, tap } from 'rxjs/operators';

    const httpOptions = {
        headers: new HttpHeaders({ 'Content-Type': 'application/json' })
    };
    @Injectable()
    export class PostService {

      private posturl = 'http://jsonplaceholder.typicode.com/posts/';
      constructor(private http:HttpClient) { 
      }
      getData():Observable<Post[]> {
          return this.http.get<Post[]>(this.posturl)
          .pipe(
             catchError(this.handleError())
          );

      }




}

but in service file i am getting following error. like 'Observable<{}>' is not assignable to type.....

  1. how to get json data through httpclient.get.
  2. How can i access data data in my post module ts file from observable object which is return by getData function of post.service.ts

Upvotes: 2

Views: 2795

Answers (3)

Prasanna
Prasanna

Reputation: 1751

Map will create new observable so that you can process the response before sending it to component.you can process as follow

public getData(){
    return this.http.get('http://jsonplaceholder.typicode.com/posts/')
    .map((response: Response) => {
        return response.json().map(this.transformData);
    })
    .catch((error: Response) => { return Observable.throw('Something went wrong');})
    .subscribe(data => console.log(data),
    (error)=> console.log('err'));
}

public transformData(r:any): Post{
    let postData = <Post>({
        userId : r.userId,
        id: r.id,
        title: r.title,
        body: r.body   
    });
    return postData;
}

.catch is added if server throws any error you can log it specifically with custom message. By using transformData() method data will be transformed

Upvotes: 0

Nicolas Gehlert
Nicolas Gehlert

Reputation: 3263

You first need to map the response and convert it from JSON into plain JS/TS objects/classes. This could look something like this

getData():Observable<Post[]> {
    return this.http.get<Post[]>(this.posturl)
        .map((resonse) => {
            return response.json().map((entry): Post => {
                // convert your stuff here and return proper type
                const result: Post = {
                    userId: result.userId,
                    id: result.id,
                    title: result.title,
                    body: result.body,
                };

                return result;
            })
        })
        .subscribe((result) => {
            console.log(result);
        });
}

Note: Don't forget to import the map function

import 'rxjs/add/operator/map';

Edit: Updated my answer with proper conversion. For Interfaces it is pretty straight forward and you could even directly cast it. (Still I prefer to use the explicit way to ensure only right properties will stay and not some unwanted accidentally get passed along. For classes this is even better, then you could add new Class() and return this and your response will always have classes.

Second Note: This assumes your json result is an array. Otherwise the .json().map() won't work and you don't need it. I'd suggest to debug response.json() to have a better idea of whats being returned :)

Upvotes: 0

Meryn
Meryn

Reputation: 63

Your issue is with your usage of the catchError operator. But I dont think you need it anyway. If you subscribe to your Observable and an error occurs, you will already get the correct error message from the backend.

To get the data from your backend write your method as follows:

public getData(): Observable<Post[]> {
    return this.http.get<Post[]>(this.posturl);
}

Then to use this data use the subscribe function of the returned observable, like this:

this.getData().subscribe(data => this.handleData(data), error => this.handleError(error));

Upvotes: 3

Related Questions