dear1
dear1

Reputation: 103

type observable of t is not assignable to t

I get the following error in Angular when I try to copy the result of the http service into variable products. Any ideas please? I think this might be related to the mapping, which I'm unsure how to do.

Btw I want to use HttpClient, not Http, and the mapping should be done automatically by using the get("api/route"); syntax, right?

Error  TS2322  (TS) Type 'Observable<Product[]>' is not assignable to type 'Product[]'.   Property 'includes' is missing in type 'Observable<Product[]>'.

Here is the code:

import { HttpClient} from "@angular/common/http"
import { Injectable } from "@angular/core"
import { Product } from "./product";
import { Observable } from "rxjs";



@Injectable()
export class DataService {
    constructor(private http: HttpClient) { }

    public products: Product[] = [];


    loadProducts(): Observable<Product[]>  {
        debugger;
        this.products = this.http.get<Product[]>("/api/products");
        return true;
    }
}

The previous version, that worked, without typesafety, is (just for the record):

...

@Injectable()
export class DataService {
    constructor(private http: HttpClient) { }

    public products = [];

     loadProducts() {
        return this.http.get("/api/products")

            .map((data: any[]) => {                               
                this.products = data;
                return true;                 
            });
    }
}

I am interested to make the example with type safety work, for this of course Product is defined in a .ts file like this:

export interface Product {
    id: number;
    category: string;
    size: string;
   //...
}

and I made sure the properties returned from the api match the properties from the interface.

Upvotes: 2

Views: 797

Answers (1)

P.S.
P.S.

Reputation: 16394

Your loadProducts method expects Observable<Product[]> to be returned, so all that you need is just follow this rule, for example, like this:

loadProducts(): Observable<Product[]>  {
  return this.http.get<Product[]>("/api/products");
}

And notice, that HTTP request returns an Observable in your case, that means, that this.products = this.http.get<Product[]>("/api/products"); will store an Observable type to this.products, not Product[] as you expected.

EDIT

"I really need to store the result of the api call inside that variable of type Product[] so I need to know how to make the conversion from Observable"

If I'm not mistaken, you can do that using take(n), which will take last n arguments from Observable and will unsubscribe automatically, in your case you can use take(1). Then, you have to handle returned Observable using .subscribe as below:

loadProducts(): Observable<Product[]>  {
  const responseSubscription: Observable<Product[]> =  this.http.get<Product[]>("/api/products");
  responseSubscription
    .take(1)
    .subscribe(products => this.products = products);
  return responseSubscription;
}

Upvotes: 1

Related Questions