Writing a generic version of this function in TypeScript is definitely possible:
function customFunction<S, V>(inputObj: {[K in keyof V]: (param: S) => V[K]}): (param: S) => V {
return function(param: S): V {
const result = {} as V;
Object.keys(inputObj).forEach((key: keyof V) => {
result[key] = inputObj[key](param);
})
return result;
}
}
const specificFunction: (params: T) => W = customFunction; // works fine
Note that the return type V
for your W
function. This means that W
can be seen as similar to (param: S) => V
. The input to customFunction
is a mapped type related to T
: it shares the same keys as V
, but its values are functions from S
to properties of V
.
The reason you can use a mapped type as input and an unmapped one as output is because TypeScript supports inference from mapped types. If not for this, a feature like the proposed "extended typeof
" would be needed to generically derive W
from
T</code.</p>
<p>In terms of implementation, I iterate over the keys of <code>inputObj
and apply each function
inputObj[key]
to the input parameter
param
.
The variable specificFunction
represents the same as customFunction
with the specific types T
and
W</code you provided. This works because TypeScript recognizes the compatibility of the generic <code>customFunction
.
However, there are some caveats to consider. The compiler may struggle to infer the type of
S</code directly from <code>customFunction
. For instance, if you call the generic
customFunction()
with a
T
input only:
declare const inputObj: T;
const outputResult = customFunction(inputObj); // (param: {}) => { prop1: T1; prop2: T2; prop3: T3; }
The outputResult
does not perfectly match
W</code... it accepts any input, not just an <code>S</code. To narrow down the input type, you'll need to manually specify the generic parameters:</p>
<pre><code>const outputResult = customFunction<S, {prop1: T1, prop2: T2, prop3: T3}>(inputObj);
Alternatively, you could narrow down the resulting outputResult
by assertion or annotation:
const w: W = customFunction(inputObj);
Hopefully, these insights are helpful. Best of luck!