How can I write a return type annotation for a function that takes an object, calls all of its methods, and returns a new object with the original keys mapped to the methods' return values?
function callMethods<T>(obj: T) {
const objResults = {};
Object.keys(obj).forEach((prop) => objResults[prop] = obj[prop]({}));
return objResults;
}
type MethodArgs = any // some complex object
console.log(callMethods({
a: (_args: MethodArgs): number => 1,
b: (_args: MethodArgs): string => "one",
c: (_args: MethodArgs): number[] => [1]
}));
// => {a: 1, b: "one", c: [1]}
// This object's type should be {a: number, b: string, c: number[]}
Right now there is no way of properly retrieving the return type of a method call and as such my solution is only partial. However there is a proposal in the works and you can read more about it here.
The best you could is at least get some more typing out of the thing you have now.
One thing you can do is use mapped types in order to retrieve the keys from T and use them as keys in the return value.
Because the return type of the methods can't be determined the value type of properties of the returned object is going to be any.
If the return types are finite you could define them as a type and use them (it's not perfect but it might be better).
If both the return types and the type of the object being passed in is known you could pass those as external parameters too, so you make a more generic function.
While this isn't the perfect solution I hope it helps you.
Note: please forgive the rewrite of the method, it seemed cleaner to use reduce.