When my component loads, I need to consume two services. Both need to be finished before it makes sense to continue. The order of completion of those is random and shouldn't be composed serially. The setup follows the pattern below.
const observables = [
this.donkeyService.getDonkey(),
this.monkeyService.getMonkey()
];
combineLatest(observables)
.subscribe(([donkeyResult, monkeyResult]) => {
if (!!donkeyResult && !!monkeyResult) {
...
}
}
We've noticed that the results aren't typed as expected. It took a while before we realized it, but the type of donkeyResult isn't Donkey, despite the definition of the server below!
getDonkey() : Observable<Donkey> { ... }
Finally, I realized that when the elements are delivered to the receiving array, they lose their typeness, since the array itself is any[]. So we manage it using casting as follows.
const observables = [
this.donkeyService.getDonkey(),
this.monkeyService.getMonkey()
];
combineLatest(observables)
.subscribe(([_1, _2]) => {
const donkeyResult = _1 as Donkey;
const monkeyResult = _2 as Monkey;
if (!!donkeyResult && !!monkeyResult) {
...
}
}
I'd like to refactor the code so that the array will retain the types specified by the service methods' signatures and won't coalesce into a common denominator any.
Is it possible to make TypeScript and/or Rxjs to have an array where the first element would be a Donkey and the second Monkey? Could I use a different data structure than an array?
I tried (and failed, of course) a bunch of different approaches including horsing around by casting the types directly in the array like so.
...
.subscribe(([_1 as Donkey, _2 as Monkey]) => { ... }
Is there a neat way to retain typeness? We're open to changing the approach altogether as we're owning this part of software and got some extra time to massage the code.
map([donkey, monkey] => { return { donkey: donkey, monkey: monkey } as {donkey: Donkey, monkey: Monkey}; })
. You still have to do the mapping by yourself with this tho – Brevet.subscribe(([(_1 as Donkey), (_2 as Monkey)]) => { ... }
... or ....subscribe(([<Donkey>_1, <Monkey>_2]) => { ... }
. – Corset.subscribe(([_1, _2]: [Donkey, Monkey]) => ...
. Combine latest should track through up to 6 typed observables, though, so I'd guess the issue is the type ofobservables
. – PsychologistcombineLatest<[Donkey, Monkey]>>(observables) .subscribe(([_1, _2]) => { const donkeyResult = _1; const monkeyResult = _2; if (!!donkeyResult && !!monkeyResult) { ... } }
– Brimmer