如何为接受对象的函数编写返回类型注释,调用其所有方法,并返回一个新对象,其中原始键映射到方法'返回值?
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[]}
答案 0 :(得分:3)
现在无法正确检索方法调用的返回类型,因此我的解决方案只是部分解决方案。但是,有一项提案正在进行中,您可以阅读更多相关信息here。
你能做的最好的事情就是至少从现有的东西中打字。
您可以做的一件事是使用映射类型来从T中检索键并将它们用作返回值中的键。
function callMethods<T>(obj: T) {
return Object.keys(obj).reduce((previous, current) => {
previous[current] = obj[current]({});
return previous;
}, {} as {[P in keyof T]: any});
}
由于无法确定方法的返回类型,因此返回对象的属性值类型将为any。
如果返回类型是有限的,你可以将它们定义为类型并使用它们(它不完美但可能更好)。
type ReturnTypes = number | string | number[];
function callMethods<T>(obj: T) {
return Object.keys(obj).reduce((previous, current) => {
previous[current] = obj[current]({});
return previous;
}, {} as {[P in keyof T]: ReturnTypes});
}
如果传入的对象的返回类型和类型都已知,那么您也可以将它们作为外部参数传递,因此您可以创建更通用的函数。
type ReturnTypes = number | string | number[];
interface Methods {
a: (args: any) => number,
b: (args: any) => string,
c: (args: any) => number[],
}
function callMethods<T, V>(obj: T) {
return Object.keys(obj).reduce((previous, current) => {
previous[current] = obj[current]({});
return previous;
}, {} as {[P in keyof T]: V});
}
let result = callMethods<Methods, ReturnTypes>({
a: (_args): number => 1,
b: (_args): string => "one",
c: (_args): number[] => [1]
});
虽然这不是一个完美的解决方案,但我希望它可以帮到你。
注意:请原谅重写方法,使用 reduce 似乎更清晰。
答案 1 :(得分:0)
从 typescript@2.1
开始,已添加 mapped types 和 typescript@2.8
conditional types 和类型推断。这个真的很容易:
type MappedReturnTypes<
T extends Record<string, (...args: any[]) => any>
> = { [K in keyof T]: ReturnType<T[K]> }