Issue
This is my first foray into RxJS, so if there is a better solution I am all for it. My goal is to collect related objects and join them (essentially a sql left join) in code. This stems from me using an Angular In Memory API object to serve as the DB until such time it is established.
When I combine Plans, Specieses, Codebooks, UpstreamModalities, and TissueProcessions this code works as expected. When I include the Probes, Imaging, and Analysises streams I get a headache of a error blob to read. Essentially every line in the array.map function throws the TS2349 error, even the ones that worked before adding the remaining three sources.
import { Component, OnInit } from '@angular/core';
import { Plan } from '../plan';
import { PlanService } from '../plan.service';
import { DatabaseService } from 'src/app/serivces/database.service';
import { combineLatest } from 'rxjs';
import { map, tap } from 'rxjs/operators';
@Component({
selector: 'app-plans-list',
templateUrl: './plans-list.component.html',
styleUrls: ['./plans-list.component.scss']
})
export class PlansListComponent implements OnInit {
plans$ = combineLatest([
this.planService.getPlans(),
this.databaseService.getSpecieses(),
this.databaseService.getCodebooks(),
this.databaseService.getUpstreamModalities(),
this.databaseService.getTissueProcessions(),
this.databaseService.getProbes(),
this.databaseService.getImagings(),
this.databaseService.getAnalysises(),
])
.pipe(
tap(x => console.log(`Plans.join lookup tables: `, x)),
map(
// destructuring
([plans,
specieses,
codebooks,
modalities,
tissues,
probes,
imagings,
analysises
]) =>
plans.map(plan =>
({
...plan,
species: specieses.find(x => x.id === plan.speciesId).shortName,
codebook: codebooks.find(x => x.id === plan.codebookId).codebookName,
upstreamModality: modalities.find(x => x.id === plan.upstreamModalityId).SOPName,
tissueProcession: tissues.find(x => x.id === plan.tissueProcessionId).SOPName,
probe: probes.find(x => x.id === plan.probeId).SOPName,
imaging: imagings.find(x => x.id === plan.imagingId).SOPName,
analysis: analysises.find(x => x.id === plan.analysisId).SOPName,
}) as Plan
)
)
)
constructor(
private planService: PlanService,
private databaseService: DatabaseService
) { }
ngOnInit() { }
}
Is this TS validation just choking up on the volume of streams? Since the code still compiles and executes as expected.
ERROR in src/app/plans/plans-list/plans-list.component.ts(40,11): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '(<U>(callbackfn: (value: Plan, index: number, array: Plan[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: StandardOperatingProcess, index: number, array: StandardOperatingProcess[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: Species, index: number, array: Species[]) => U, thisArg?: any) => U[...' has no compatible call signatures.
src/app/plans/plans-list/plans-list.component.ts(43,24): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ <S extends Plan>(predicate: (this: void, value: Plan, index: number, obj: Plan[]) => value is S, thisArg?: any): S; (predicate: (value: Plan, index: number, obj: Plan[]) => boolean, thisArg?: any): Plan; } | { ...; } | { ...; } | { ...; }' has no compatible call signatures.
src/app/plans/plans-list/plans-list.component.ts(44,25): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ <S extends Plan>(predicate: (this: void, value: Plan, index: number, obj: Plan[]) => value is S, thisArg?: any): S; (predicate: (value: Plan, index: number, obj: Plan[]) => boolean, thisArg?: any): Plan; } | { ...; } | { ...; } | { ...; }' has no compatible call signatures.
src/app/plans/plans-list/plans-list.component.ts(45,33): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ <S extends Plan>(predicate: (this: void, value: Plan, index: number, obj: Plan[]) => value is S, thisArg?: any): S; (predicate: (value: Plan, index: number, obj: Plan[]) => boolean, thisArg?: any): Plan; } | { ...; } | { ...; } | { ...; }' has no compatible call signatures.
src/app/plans/plans-list/plans-list.component.ts(46,33): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ <S extends Plan>(predicate: (this: void, value: Plan, index: number, obj: Plan[]) => value is S, thisArg?: any): S; (predicate: (value: Plan, index: number, obj: Plan[]) => boolean, thisArg?: any): Plan; } | { ...; } | { ...; } | { ...; }' has no compatible call signatures.
src/app/plans/plans-list/plans-list.component.ts(47,22): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ <S extends Plan>(predicate: (this: void, value: Plan, index: number, obj: Plan[]) => value is S, thisArg?: any): S; (predicate: (value: Plan, index: number, obj: Plan[]) => boolean, thisArg?: any): Plan; } | { ...; } | { ...; } | { ...; }' has no compatible call signatures.
src/app/plans/plans-list/plans-list.component.ts(48,24): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ <S extends Plan>(predicate: (this: void, value: Plan, index: number, obj: Plan[]) => value is S, thisArg?: any): S; (predicate: (value: Plan, index: number, obj: Plan[]) => boolean, thisArg?: any): Plan; } | { ...; } | { ...; } | { ...; }' has no compatible call signatures.
src/app/plans/plans-list/plans-list.component.ts(49,25): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type '{ <S extends Plan>(predicate: (this: void, value: Plan, index: number, obj: Plan[]) => value is S, thisArg?: any): S; (predicate: (value: Plan, index: number, obj: Plan[]) => boolean, thisArg?: any): Plan; } | { ...; } | { ...; } | { ...; }' has no compatible call signatures.
Solution
This is true, maximum number of source Observables is 6, see https://github.com/ReactiveX/rxjs/blob/master/src/internal/observable/combineLatest.ts#L68.
However, The only reason is that it's unlikely to have so many inputs so there are no function overloads defined for that. This still doesn't restrict you from combining multiple combineLatest
s:
combineLatest([
combineLatest([s1, s2, ...]),
combineLatest([s7, s8, ...]),
]).pipe(
map(([results1, results2]) => [...results1, ...results2]),
);
Btw, this is a TypeScript error that you should be able to suppress with @ts-ignore
(even though you might miss other TypeScript errors later):
// @ts-ignore
plans$ = combineLatest([
this.planService.getPlans(),
this.databaseService.getSpecieses(),
...
this.databaseService.getAnalysises(),
])
Answered By - martin
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.