angular - combineLatest kastar TS2349 med 6 eller fler strömmar
Detta är mitt första försök med RxJS, så om det finns en bättre lösning är jag öppen för det. Mitt mål är att samla relaterade objekt och slå ihop dem (i princip en SQL-left join) i koden. Detta kommer från att jag använder ett Angular In Memory API-objekt för att fungera som databasen tills dess att den är etablerad.
När jag kombinerar Plans, Specieses, Codebooks, UpstreamModalities och TissueProcessions fungerar den här koden som förväntat. När jag inkluderar Probes, Imaging och Analysises-strömmarna får jag en huvudvärk av ett felblock att läsa. I princip varje rad i array.map-funktionen ger TS2349-felet, även de som fungerade innan jag lade till de återstående tre källorna.
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() { }
}
Är denna TS-validering bara överbelastad på grund av volymen av strömmar? Eftersom koden fortfarande kompileras och körs som förväntat.
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.
Svar #1
Detta är sant, maximalt antal käll-Observables är 6, se https://github.com/ReactiveX/rxjs/blob/master/src/internal/observable/combineLatest.ts#L68.
Men den enda anledningen är att det är osannolikt att ha så många indata, så det finns inga funktionsöverlagringar definierade för det. Detta hindrar dig fortfarande inte från att kombinera flera combineLatest:
combineLatest([
combineLatest([s1, s2, ...]),
combineLatest([s7, s8, ...]),
]).pipe(
map(([results1, results2]) => [...results1, ...results2]),
);
Förresten, detta är ett TypeScript-fel som du borde kunna undertrycka med @ts-ignore (även om du kan missa andra TypeScript-fel senare):
// @ts-ignore
plans$ = combineLatest([
this.planService.getPlans(),
this.databaseService.getSpecieses(),
...
this.databaseService.getAnalysises(),
])
Svar #2
Bara för fullständighetens skull (och för att ha alla svar tillgängliga på Stackoverflow, och inte i någon länk), lösningen från frågan som Balu länkade är helt enkelt att deklarera typerna som varje observable kommer att utsända:
combineLatest<any>(a$, b$, c$, d$, e$, f$).pipe(
// Manually typed arguments below :(
map(([a, b, c, d, e, f]: [string, number, string, Foo, Bar, Baz]) => doStuff(a, b, c, d, e, f))
)
Detta kan förenklas avsevärt genom att definiera en ny typ med de förväntade parametertyperna.
export type CombinedSources = [string, number, string, Foo, Bar, Baz];
combineLatest<any>(a$, b$, c$, d$, e$, f$).pipe(
map(([a, b, c, d, e, f]: CombinedSources) => doStuff(a, b, c, d, e, f))
)
