Work around for more than 6 forkJoin parameters?

As the answer explains in the question you linked, the maximum number of arguments is only constrained by the type definitions -- not the runtime source itself. The type definitions are useful because they declare the array element types that will be produced for the next step of the observable stream (the types for [param, promise1, promise2, ...] in your case).

It sounds like strict type safety around the assignments in your subscription handler is what's causing the issue for you. Since you have more than 6 observables, it defaults the resulting parameters to a shared type which likely does not match the types of the fields that you are trying to assign.

There are a few ways around this. You can cast the arguments in your subscription handler or you can add your own types yourself. Casting arguments is the quick-and-dirty solution, but it causes you to lose type safety. Adding types yourself would let you maintain type safety, but it could also mean that you end up with any number of factory method declarations. Place the below in a type definition file (*.d.ts) anywhere in your project. I like to place type definitions like this in a typings/ directory at a sibling level to my app/ directory.

import { Observable, SubscribableOrPromise } from 'rxjs/Observable';

declare module 'rxjs/observable/ForkJoinObservable' {
    namespace ForkJoinObservable {
        export function create<T, T2, T3, T4, T5, T6, T7>(v1: SubscribableOrPromise<T>, v2: SubscribableOrPromise<T2>, v3: SubscribableOrPromise<T3>, v4: SubscribableOrPromise<T4>, v5: SubscribableOrPromise<T5>, v6: SubscribableOrPromise<T6>, v7: SubscribableOrPromise<T7>): Observable<[T, T2, T3, T4, T5, T6, T7]>;
        export function create<T, T2, T3, T4, T5, T6, T7, R>(v1: SubscribableOrPromise<T>, v2: SubscribableOrPromise<T2>, v3: SubscribableOrPromise<T3>, v4: SubscribableOrPromise<T4>, v5: SubscribableOrPromise<T5>, v6: SubscribableOrPromise<T6>, v7: SubscribableOrPromise<T7>, project: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, v7: T7) => R): Observable<R>;
    }
}

This process is explained in more detail in the TypeScript documentation page for Declaration Merging.


Edit: It looks like I'm using an older version of RxJS and the structure has changed a bit since. The following should be closer to the type declarations that should work with the current structure:

declare module 'rxjs/Observable' {
    namespace Observable {
        export function forkJoin<T, T2, T3, T4, T5, T6, T7>(sources: [ObservableInput<T>, ObservableInput<T2>, ObservableInput<T3>, ObservableInput<T4>, ObservableInput<T5>, ObservableInput<T6>, ObservableInput<T7>]): Observable<[T, T2, T3, T4, T5, T6, T7]>;
        export function forkJoin<T, T2, T3, T4, T5, T6, T7>(v1: ObservableInput<T>, v2: ObservableInput<T2>, v3: ObservableInput<T3>, v4: ObservableInput<T4>, v5: ObservableInput<T5>, v6: ObservableInput<T6>, v7: ObservableInput<T7>): Observable<[T, T2, T3, T4, T5, T6, T7]>;
    }
}

I am basing these off of the current forkJoin type declarations.

As far as the module augmentation, the code above modifies the type declarations for the module defined by the absolute path 'rxjs/Observable'. This is the same as the import path that you would use when importing the Observable class. The module as defined by RxJS exports the Observable class and its fields. Our augmentation to that module modifies it by using the namespace block. This allows us to add type declarations under the Observable namespace (e.g., type declarations for Observable.myFunctionOrField) which looks the same as calling static functions on it. Effectively, this declares the additional Observable.forkJoin function possibilities.


Starting from version 6.5 of rxJs you can use dictionary of values to put any number of observables inside forkJoin see the first example here

    forkJoin({first: of(1), second: of(2), third: of(3)})
             .subscribe(result => {console.log(result.first)});

Thanks @MikeHill for getting me pointed in the correct direction. The solution that ended up working for me was to add a typings.d.ts to the angular-cli generated src folder. I believe you can also use a typings folder in the same location but you will need to update your tsconfig.app.json file, see this article for more information. https://github.com/angular/angular-cli/blob/6449a753641340d8fc19a752e1a1ced75f974efa/docs/documentation/1-x/stories/third-party-lib.md

typings.d.ts for 7 parameters with forkJoin

import { ObservableInput, Observable } from 'rxjs';
import { forkJoin } from 'rxjs/internal/observable/forkJoin';

declare module 'rxjs/internal/observable/forkJoin' {
  export function forkJoin<T, T2, T3, T4, T5, T6, T7>(
    sources: [
      ObservableInput<T>,
      ObservableInput<T2>,
      ObservableInput<T3>,
      ObservableInput<T4>,
      ObservableInput<T5>,
      ObservableInput<T6>,
      ObservableInput<T7>
    ],
  ): Observable<[T, T2, T3, T4, T5, T6, T7]>;
  export function forkJoin<T, T2, T3, T4, T5, T6, T7>(
    v1: ObservableInput<T>,
    v2: ObservableInput<T2>,
    v3: ObservableInput<T3>,
    v4: ObservableInput<T4>,
    v5: ObservableInput<T5>,
    v6: ObservableInput<T6>,
    v7: ObservableInput<T7>,
  ): Observable<[T, T2, T3, T4, T5, T6, T7]>;
}