In my angular 6 application, I want to filter before it switchMap
to inner Observable as below:
Basically, What I want to do is if the store selector gives me pertaining data for a given string I will use the response in switchMap
to fire the inner observable and will do a subscription.
The idea here is that if filtration succeeds do find and data for the filters response using switchMap
this._store.pipe(select(getDetails)).pipe(map((details: detail[]) => {
return of(details.filter(({ tagName }) => tagName ===this.videoTagName))})
switchMap((data:detail)=>this._store.pipe(select(getVideosByID(data.contentIds[0]))))).subscribe(data=>{
console.log("Data",data)
})
The above code gives the error below:
Type 'detail' is missing the following properties from type 'Observable<detail[]>': _isScalar, source, operator, lift, and 10 more.ts(2345)
will combineLatest
help here? or something I need to do with switchMap
only.. ?
CodePudding user response:
A few things:
You should probably define types or classes/interfaces in a way that they won't conflict with variables. Usually people will capitalize types, for instance you'd have
type Detail = ...
so that you can then defineconst detail: Detail = ...
.Assuming that a detail is not an Observable, you should not use
of
in the "project" argument of RxJs'smap
. The "project" argument ofmap
is a function that takes as its argument the value emitted by an observable, and returns a new value that will be emitted instead. Here if you returnof
, your Observable will emit an Observable (which is usually not what you want). This is why you get your error:switchMap
right below expects to be piped to an Observable that emits adetail
, but instead it gets anObservable<detail[]>
. If you fix that, you'll emitdetails
instead ofdetail
, which isn't perfect yet but we're getting closer.If you want to filter a unique detail (and not a list of details), you should use
.find()
instead of.filter()
. Filtering returns an array of all elements that match the predicate (maybe it's an array of 1 element only, but it's still an array). Find returns the first element that matches. Now we're emitting adetail
, so the typing inside switchMap will be ok and the error will go away.You don't need to chain
.pipe()
calls, you can just chain the arguments inside of a single pipe. This applies to the first two pipes, but obviously not to the one inside the switchMap, since if you move it inside of the "main" pipe,detail
won't be in the scope anymore.
With all of this, you get the following code, which should work:
this._store.pipe(
select(getDetails),
map((details: Detail[]) => details.find(
({ tagName }) => tagName === this.videoTagName
)),
switchMap((detail: Detail) => this._store.pipe(
select(getVideosByID(detail.contentIds[0])),
)),
).subscribe(data => console.log("Data", data));