Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return when subscribing. ... Type 'Subscription' is missing the following properties

I am subscribing a response from an Angular service:

  books: BookModel[] = [];

  constructor(private bookService: BookService) { }

  ngOnInit() {

    this.books = this.getBooks();

  }

  getBooks(): BookModel[] {

    return this.bookService.getByCategoryId(1).subscribe((payload: Payload<GetBooksResponse>) => {

      return payload.result.map((response: GetBooksResponse) => { 

        return {
          id: response.id, 
          title: response.title
        };

      });

    });

  }

When I add return to this.bookService, e.g., return this.bookService I get the error:

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

How can I use return to make this work?

Update: BookModel:

export interface BookModel {
  id: number;
  title: string;
}
like image 256
Miguel Moura Avatar asked Jan 07 '19 15:01

Miguel Moura


3 Answers

You are trying to assign a Subscription into an array that is why you are getting these error:

I made this example using Observables and async pipe, I hope it helps you:

TS:

 /***
   *  books$ Observable is looking to any response
   *  of the method getByCategoryId. It is being displayed with async pipe in the view.
   */
  books$ = this.bookService.getByCategoryId(1);

  books: BookModel[];

  constructor(private bookService: BookService) { }

  ngOnInit() {
    this.getBooks();
  }

  /***
   *  Getbooks method does not return anything, 
   *  after the subscribe, a map is assigning the value to the books propertie
   *  which is in being render in the view without async pipe. 
   */
  getBooks(): void {
    this.bookService.getByCategoryId(1)
      .subscribe((payload: Payload<GetBooksResponse>) => {

        this.books = payload.result.map((response: GetBooksResponse) => {
          return <BookModel>{
            id: response.id,
            title: response.title
          };
        });

      });
  }

HTML:

<div *ngFor="let book of (books$ | async).result">
    {{ book | json }}
</div>

<br/>
<h3> Not Using | async </h3>

<div *ngFor="let book of books">
  {{ book | json }}
</div>

Try online at this link: https://stackblitz.com/edit/angular-k9pzmw

If you ask me which approach is better, I would say it depends.

Async pipe with observable is my favorite to only show 'dumb data' in the view, but you should keep the subscription solution if you need this information in the component for anything else.

like image 155
Thomaz Capra Avatar answered Nov 15 '22 00:11

Thomaz Capra


You need to return

getBooks(): Observable<BookModole[]> { ... }

then:

this.getBooks().subscribe(res => { this.books = res; });
like image 38
phucnh Avatar answered Nov 15 '22 02:11

phucnh


I tried to save a Subscription in a typed Observable<T> variable. Simply had to not subscribe since I use the async pipe in my HTML.

like image 1
Ruben Szekér Avatar answered Nov 15 '22 00:11

Ruben Szekér