Given
type Loadable<T> = () => T
type LoadableCombinerResult<T> = { result: T }
I would like define types for a function with input like this:
- variable number of
Loadable<ResponseDataType>inputs with differentResponseDataTypefor each input, combinertaking data results of above loadables.
The function would take care of handling error states and loading progress of loadables, plus few other things. The function would call combiner only if all loadables are successfully loaded.
This is possible to implement in untyped JavaScript. However, I fail to properly type it in TypeScript.
Non-variadic typing would look like this:
function useLoadableCombiner2<TResult, T1, T2>(
combiner: (data1: T1, data2: T2) => TResult,
loadable1: Loadable<T1>,
loadable2: Loadable<T2>
): LoadableCombinerResult<TResult> { ... }
function useLoadableCombiner3<TResult, T1, T2, T3>(
combiner: (data1: T1, data2: T2, data3: T3) => TResult,
loadable1: Loadable<T1>,
loadable2: Loadable<T2>,
loadable3: Loadable<T3>
): LoadableCombinerResult<TResult> { ... }
function useLoadableCombiner4<TResult, T1, T2, T3, T4>(
combiner: (data1: T1, data2: T2, data3: T3, data4: T4) => TResult,
loadable1: Loadable<T1>,
loadable2: Loadable<T2>,
loadable3: Loadable<T3>,
loadable4: Loadable<T4>
): LoadableCombinerResult<TResult> { ... }
function useLoadableCombinerN<...>(...): LoadableCombinerResult<TResult> { ... }
Is it possible to type this in TypeScript as one function in one declaration?
It could be an array/typed-tuple instead of variable number of arguments.
The goal is to put in variable number of loadables in, and then being able to call typed combiner with all the data, after a successful load of everything.
You can use a generic tuple type
Tto represent the rest parameter list tocombiner, and then map over that tuple type to get the type of theloadablerest parameter:Now when you call
useLoadableCombiner, the type checker can inferTeither from the parameter types ofcombineror, if you don't annotate those, from the return types of each element ofloadable:Here
Tis inferred fromloadableis of type[Loadable<string>, Loadable<number>, Loadable<Date>], and thencombineris checked (you can see how even though we don't annotatestr,num, anddat, the type checker knows their types fromloadable) and returns aboolean, and thusxis of typeLoadableCombinerResult<boolean>.Playground link to code