Casting results from Observable.forkJoin to their respective types in Angular 2

Viewed 15969

Let say I have a component in Angular 2 that needs to load 2 different things from the server before the page is displayed. I'd like all of those things to fire off and call one event handler when they come back telling the page isLoaded = true. Let's say I have a service class that looks like this.

export class MyService {
   getStronglyTypedData1(): Observable<StrongData1[]>{
      return this.http.get('http://...').map((response:Response) => <StrongData1[]>response.json());
   }
   getStronglyTypedData2(): Observable<StrongData2[]>{
         return this.http.get('http://...').map((response:Response) => <StrongData2[]>response.json());
   }
}

Then I have a component that uses that service class like this.

export class MyComponent implements OnInit {
   isLoaded = false;
   stronglyTypedData1: StrongData1[];
   stronglyTypedData2: StrongData2[];

   constructor(private myService:MyService){ }

   ngOnInit(){
      var requests [ 
         this.myService.getStronglyTypedData1(),
         this.myService.getStronglyTypedData2()
      ];
      Observable.forkJoin(requests).subscribe(
         results => {
            this.stronglyTypedData1 = results[0];
            this.stronglyTypedData2 = results[1];
            this.isLoaded = true;
         });
   }
}

The TypeScript compiler is complaining that it cant convert type object to type StrongData1[]. If I change StrongData1 and StrongData2 to "any", everything works fine. I'd rather not do that though because I'm losing the benefit of TypeScript's strong typings.

How do I cast the results from forkJoin to their respective types?

3 Answers

In Typescript you can use destructuring on function parameters (a tuple in this case):

const requests = [ 
    this.myService.getStronglyTypedData1(),
    this.myService.getStronglyTypedData2()
];
forkJoin(requests)
    .subscribe(([data1, data2]: [StrongData1[], StrongData2[]]) => {
        this.stronglyTypedData1 = data1;
        this.stronglyTypedData2 = data2;
        this.isLoaded = true;
    });
Related