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.. ?
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 define const detail: Detail = ...
.
Assuming that a detail is not an Observable, you should not use of
in the "project" argument of RxJs's map
. The "project" argument of map
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 return of
, 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 a detail
, but instead it gets an Observable<detail[]>
. If you fix that, you'll emit details
instead of detail
, 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 a detail
, 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));