ultimatecourses / angular-pro-app-seed

Seed project for Angular Pro final application
112 stars 360 forks source link

meals$ observable type error #6

Closed evgeniush closed 5 years ago

evgeniush commented 6 years ago

Hey Todd,

In MealsService defining meals$ at line 22 I'm having a type error:

meals$: Observable<Meal[]> = this.db.list(meals/${this.uid}) .do(next => this.store.set('meals', next));

Type 'Observable<{}>' is not assignable to type 'Observable<Meal[]>'. Type '{}' is not assignable to type 'Meal[]'. Property 'includes' is missing in type '{}'.

which should not be there according to AngularFireDatabase.list definition

(method) AngularFireDatabase.list(pathOrRef: PathReference, opts?: FirebaseListFactoryOpts): FirebaseListObservable<any[]>

Any help?

angular-pro-app-seed/src/health/shared/services/meals/meals.service.ts Branch: 09-meals-component node 8 Windows 10

screen shot 2018-03-06 at 10 02 06 am screen shot 2018-03-06 at 10 14 12 am

ibaiimaz commented 6 years ago

You can explicitly set the type using the current example:

meals$: Observable<Meal[]> = (this.db.list(`meals/${this.uid}`) as Observable<Meal[]>)
  .do(next => this.store.set('meals', next));

I'm not sure if it's a good practice but it works.

Hope it helps!

evgeniush commented 6 years ago

no, but still, db.list returns not correct data type

[ts] Type 'AngularFireList<{}>' cannot be converted to type 'Observable<Meal[]>'. [ts] Type 'AngularFireList<{}>' cannot be converted to type 'Observable<Meal[]>'. Property '_isScalar' is missing in type 'AngularFireList<{}>'.

aucevica commented 6 years ago

@ibaiimaz It works! Tks

hypocore commented 6 years ago

For rxjs 6.2.2, this.db.list needs the type you are requesting:

    meals$: Observable<Meal[]> = this.db.list<Meal>(`meals/${this.uid}`).valueChanges()
    .pipe(
        tap(result => this.store.set('meals', result))
    );

If you are still using the do operator, it will probably be this:

meals$: Observable<Meal[]> = this.db.list<Meal>(`meals/${this.uid}`).valueChanges()
  .do(next => this.store.set('meals', next));
hypocore commented 6 years ago

What I've posted above works, but valueChanges does not return the key that is required in further videos. To get the key, you would have to use snapshotChanges() and map the key to each meal in the meals array.

In meals.service.ts:

    meals$: Observable<Meal[]> = this.db.list<Meal>(`meals/${this.uid}`).snapshotChanges()
    .pipe(
        map(meals => 
            meals.map(meal => ({ $key: meal.key, ...meal.payload.val() }))
        ),
        tap(meals => this.store.set('meals', meals))
    );

which is probably like this using the old operators:

    meals$: Observable<Meal[]> = this.db.list<Meal>(`meals/${this.uid}`).snapshotChanges()
        .map(meals => 
            meals.map(meal => ({ $key: meal.key, ...meal.payload.val() }))
          )
        .do(meals => this.store.set('meals', meals))