TypeScript type analysis work in top->down way. It means that it is equal to the program data flow where the data also is passed top->down. TypeScript is analyzing control-flow, but it is using for it informations given from the top, not from the bottom.
Consider such example of function:
function functionMaker(x: string, y: string) {
return () => x + y;
}
Above function return another function. There is none explicit typing in the definition of the anonymous function returned, but TS is able to analyse that functionMaker always returns () => string type of function.
Doing that another way around is not possible, as TS cannot predict what exactly you will do with the arguments. Consider below:
function functionA(x: string, y: number, z: SpecialType): void { }
function functionB(x: number): void { }
const functionWrapper: (x, y, z) => {
functionA(x, y, z); // x should be string
functionB(x); // x should be number
}
Now TS has two functions which are using one argument, but both of them have different requirement of the type. Any solving of this puzzle is wrong, as one or another function will fail.
In summary - type analysis is done top-down. But we can solve your issue by creating generic function which will wrap another.
function functionA(x: string, y: number, z: SpecialType): void { }
const wrap = <X, Y, Z, R>(f: (x: X, y: Y, z: Z) => R) => (x: X, y: Y, z: Z): R => f(x,y,z);
const functionWrapper = wrap(functionA);
Our wrap is clearly defined as a wrapper, it means that its purpose is to infer the types from the given function and create another function which has the same arguments and the same return.