Prior to TypeScript 3.0, inferring types for N-arity functions involved creating an arbitrary number of function overloads for known generic arguments, then writing the function implementation using something like any typed rest parameters. TypeScript 3.0 changed this, so that a generic type can extend any[], which acts as a generic tuple.
This change makes sense and works fine for me with generic parameters themselves, but I can't get the types to flow through to return types as I could prior to 3.0.
Here's an example:
const takeToPromise = <T>(obs$: Observable<T>): Promise<T> =>
obs$.pipe(take(1)).toPromise();
export function resolveObservables(): Promise<any[]>;
export function resolveObservables<T1>(o1: Observable<T1>): Promise<[T1]>;
export function resolveObservables<T1, T2>(o1: Observable<T1>, o2: Observable<T2>): Promise<[T1, T2]>;
export function resolveObservables<T1, T2, T3>(o1: Observable<T1>, o2: Observable<T2>, o3: Observable<T3>): Promise<[T1, T2, T3]>;
// Etc on the overloads
export function resolveObservables(...obs: (Observable<any>)[]): Promise<any[]> {
return Promise.all(obs.map(takeToPromise));
}
Let's say I have only 3 overloads (up to T3). If I use resolveObservables by spreading an array into the function call, in TS 3.0, I will get an error:
Expected 0-3 arguments, but got 0 or more.
I can use this just fine with a fixed arity call, but as soon as I try to spread, I get errors. Any attempts to make this work have failed in some way or another. For example:
export function resolveObservables<T, U extends Observable<T>[]>(...obs: U): Promise<T[]>;
Will fail to capture any types (types are {}).
Is there some way to modify these types so I can get types to flow through without losing the ability to use spread arguments? In cases where I am using spread, I don't really care about the types, and if I did, I assume I could just use a tuple type. But based on what I've tried so far, I can either use spread but lose types, or have types but can't use spread.
What am I missing here?