156

I have this Product interface:

export interface Product{
  code: string;
  description: string;
  type: string;
}

Service with method calling product endpoint:

  public getProducts(): Observable<Product> {
    return this.http.get<Product>(`api/products/v1/`);
  }
  

And component where I use this service to get the Products.

export class ShopComponent implements OnInit {
    public productsArray: Product[];
    
    ngOnInit() {
        this.productService.getProducts().subscribe(res => {
          this.productsArray = res;
        });
    }
}

With this state I'm getting error:

[ts] Type 'Product' is missing the following properties from type 'Product[]': length, pop, push, concat, and 26 more. [2740]

Removing typing on productsArray variable removes the error, but don't get why this is not working, since server response is an array of objects in the type of Products?

live-love
  • 48,840
  • 22
  • 240
  • 204
mpro
  • 14,302
  • 5
  • 28
  • 43

8 Answers8

146

You are returning Observable<Product> and expecting it to be Product[] inside subscribe callback.

The Type returned from http.get() and getProducts() should be Observable<Product[]>

public getProducts(): Observable<Product[]> {
    return this.http.get<Product[]>(`api/products/v1/`);
}
Amit Chigadani
  • 28,482
  • 13
  • 80
  • 98
23

You have forgotten to mark the getProducts return type as an array. In your getProducts it says that it will return a single product. So change it to this:

public getProducts(): Observable<Product[]> {
    return this.http.get<Product[]>(`api/products/v1/`);
  }
Fredrik_Borgstrom
  • 2,504
  • 25
  • 32
16

For those newbies like me, don't assign variable to service response, meaning do

export class ShopComponent implements OnInit {
  public productsArray: Product[];

  ngOnInit() {
      this.productService.getProducts().subscribe(res => {
        this.productsArray = res;
      });
  }
}

Instead of

export class ShopComponent implements OnInit {
    public productsArray: Product[];

    ngOnInit() {
        this.productsArray = this.productService.getProducts().subscribe();
    }
}
Brady Huang
  • 1,852
  • 20
  • 23
7

You must specify which type the response is:

this.productService.getProducts().subscribe(res => {
    this.productsArray = res;
});

Try this:

this.productService.getProducts().subscribe((res: Product[]) => {
    this.productsArray = res;
});
2

I had the same problem and I solved as follows define an interface like mine

export class Notification {
    id: number;
    heading: string;
    link: string;
}

and in nofificationService write

allNotifications: Notification[]; 
  //NotificationDetail: Notification;  
  private notificationsUrl = 'assets/data/notification.json';  // URL to web api 
  private downloadsUrl = 'assets/data/download.json';  // URL to web api 

  constructor(private httpClient: HttpClient ) { }

  getNotifications(): Observable<Notification[]> {    
       //return this.allNotifications = this.NotificationDetail.slice(0);  
     return this.httpClient.get<Notification[]>

(this.notificationsUrl).pipe(map(res => this.allNotifications = res))
      } 

and in component write

 constructor(private notificationService: NotificationService) {
   }

  ngOnInit() {
      /* get Notifications */
      this.notificationService.getNotifications().subscribe(data => this.notifications = data);
}
1

I got the same error message on GraphQL mutation input object then I found the problem, Actually in my case mutation expecting an object array as input but I'm trying to insert a single object as input. For example:

First try

const mutationName = await apolloClient.mutate<insert_mutation, insert_mutationVariables>({
      mutation: MUTATION,
      variables: {
        objects: {id: 1, name: "John Doe"},
      },
    });

Corrected mutation call as an array

const mutationName = await apolloClient.mutate<insert_mutation, insert_mutationVariables>({
      mutation: MUTATION,
      variables: {
        objects: [{id: 1, name: "John Doe"}],
      },
    });

Sometimes simple mistakes like this can cause the problems. Hope this'll help someone.

Nipun Ravisara
  • 3,629
  • 3
  • 20
  • 35
1

For me the error was caused by wrong type hint of url string. I used:

export class TodoService {

  apiUrl: String = 'https://jsonplaceholder.typicode.com/todos' // wrong uppercase String

  constructor(private httpClient: HttpClient) { }

  getTodos(): Observable<Todo[]> {
    return this.httpClient.get<Todo[]>(this.apiUrl)
  }
}

where I should have used

export class TodoService {

  apiUrl: string = 'https://jsonplaceholder.typicode.com/todos' // lowercase string!

  constructor(private httpClient: HttpClient) { }

  getTodos(): Observable<Todo[]> {
    return this.httpClient.get<Todo[]>(this.apiUrl)
  }
}
Michał Jabłoński
  • 1,129
  • 1
  • 13
  • 15
0

This error could also be because you are not subscribing to the Observable.

Example, instead of:

this.products = this.productService.getProducts();

do this:

   this.productService.getProducts().subscribe({
    next: products=>this.products = products,
    error: err=>this.errorMessage = err
   });
live-love
  • 48,840
  • 22
  • 240
  • 204