0

I would like to return an Observable object from a Observable Array or objects. getTodoById() I tried to return by using pipe & map operators. Err messsages:

Type 'Observable<Todo | undefined>' is not assinable to type 'Observable'. Type 'Todo | undefined is not assignable to type 'Todo'. ts(2322)

I tried assigning "?" sign but it wasn't very useful. Maybe I did it wrong. This is my current code. I tried Observable<Todo | undefined> as a return type to getById() it showed the same error.

todo service:

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable, of, Subscription, pipe } from 'rxjs';
import { map } from 'rxjs/operators';
import { FilterBy } from '../models/filterBy.model';
import { SortBy } from '../models/sortBy.model';
import { Todo } from '../models/todo.model';

// this is BehaviorSubject - Can get .next
  private _todos$ = new BehaviorSubject<Todo[]>([])

  // this is an Observable - we CANNOT do .next.
  // It acts like a getter - You can list to it's changes
  // this makes a good separation!
  public todos$ = this._todos$.asObservable();

      public getById(id: string): Observable<Todo> {
    return this.todos$.pipe(map(todos=> todos.find(todo => todo._id === id)))
  }

todo model:

export interface Todo {
  _id: string,
  title:string,
  date:Date,
  isDone:boolean,
  importance:number
}
8
  • Observable<Todo | undefined> Commented Nov 7, 2021 at 12:36
  • Didn't help. to add : Observable<Todo | undefined> as a return type to getVyId @MikeOne Commented Nov 7, 2021 at 12:45
  • 2
    Array.prototype.find() returns the found item or undefined. Changing return type of function should fix. Were you getting a different error after the change? Commented Nov 7, 2021 at 12:48
  • Could you try .filter() instead of map and find? Commented Nov 7, 2021 at 12:53
  • @BizzyBob - I got the exact error after changing the return type ( Added undefined) Commented Nov 7, 2021 at 14:00

3 Answers 3

2

Have you tried to add filter operator

return this.todos$.pipe(
  map(todos=> todos.find(todo => todo._id === id)),
  filter(todo => !!todo)
)
Sign up to request clarification or add additional context in comments.

1 Comment

Why use filter ??
1

You need to add undefined as a return type to getById because you are using find() and typescript is smart enough to know that your array will not always return a value.

  public getById(id: string): Observable<Todo | undefined> {
    return this.todos$.pipe(map(todos=> todos.find(todo => todo._id === id)))
  }

Or if you don't want to return undefined as a return value you can use casting as follows:

  public getById(id: string): Observable<Todo> {
    return this.todos$.pipe(map(todos=> todos.find(todo => todo._id === id))) as Observable<Todo>
  }

but I prefer the first solution

Comments

0

Thank you for your answers and trying to help. I decided to go for a simpler way which is:

  public getById(id: string): Todo | undefined{
    const todos = this._todos$.getValue();
    return todos.find(todo => todo._id === id);
  }

1 Comment

"Important note from the author of RxJS 5: Using getValue() is a HUGE red flag you're doing something wrong. It's there as an escape hatch. Generally everything you do with RxJS should be declarative. getValue() is imperative. If you're using getValue(), there's a 99.9% chance you're doing something wrong or weird. – Ben Lesh Jul 21 '17 at 0:01 Link here: stackoverflow.com/questions/37089977/… (see the answers)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.