Type 'Observable<Object>' is not assignable to type 'Observable<IUser[]>'

Sam Kelham picture Sam Kelham · Feb 17, 2018 · Viewed 29.3k times · Source

In my Api service I have this simple getUsers function to fetch all of the users on the api.

public getUsers(url: string): Observable<IUser[]>  {
  return this._http.get(url);
} 

This is my IUser interface, I have made all the field optional for now.

export interface IUser {
  id?: string;
  first_name?: string;
  last_name?: string;
  location?: string;
  followers?: string;
  following?: string;
  checkins?: string;
  image?: string;
}

and here is how I have used the service in my component:

export class SocialOverviewContainerComponent implements OnInit {
  public userData = [];
  public showForm = {};
  private _apiService: ApiService;

  constructor(apiService: ApiService) {
    this._apiService = apiService
  }

  public ngOnInit(): void {
    this.getUsersData();
  }

  public getUsersData()  {
    this._apiService.getUsers(ApiSettings.apiBasepath + 'users/')
      .subscribe(users => {
        this.userData = users;
    })
  }
}

and this is is the Type error I get when it compiles

ERROR in src/app/services/api.service.ts(18,5): error TS2322: Type 'Observable<Object>' is not assignable to type 'Observable<IUser[]>'.
  Type 'Object' is not assignable to type 'IUser[]'.
    The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?
      Property 'includes' is missing in type 'Object'.

I thought this might be because my response doesn't match the interface, which I have double check and it does. And I have also made the field optional for now to make sure.

I know I can fix this by casting the observable as any, but doesn't that defeat the point of using Typescript?

Any help on where I am going wrong would be great

Thanks in advance

Answer

th3n3wguy picture th3n3wguy · Feb 17, 2018

There are two ways to do this, and it depends on which version of RxJS / Angular that you are using. Here are the two ways to do it depending on your versions:

// Using RxJS v4 / Angular v2-4. I assume that you're using the HttpModule...
import 'rxjs/add/operator/map';

public getUsers(url: string): Observable<IUser[]> {
  return this._http.get(url)
    .map((response: Response) => <IUser[]>response.json());
}


// Using RxJS v5 / Angular 5+ (at the moment). I assume that you're using the HttpClientModule, as the HttpModule was deprecated in Angular v4.
public getUsers(url: string): Observable<IUser[]> {
  return this._http.get<IUser[]>(url);
}