2017-06-04 78 views
2

如何为一个函数编写返回类型注释,该函数接受一个对象,调用其所有方法并返回一个新对象,其中原始键映射到方法的返回值?用于调用对象方法的返回类型注释

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[]} 

回答

2

现在没有办法正确检索方法调用的返回类型,因此我的解决方案只是部分。然而,在作品中有一个提案,你可以阅读更多有关它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}); 
} 

由于所述方法的返回类型不能确定返回的对象的属性的值类型将是任何。

如果返回类型是有限的,你可以将它们定义为一个类型并使用它们(它并不完美,但可能会更好)。

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] 
}); 

虽然这不是完美的解决方案,我希望它可以帮助你。

注意:请原谅重写的方法,使用看起来更清洁减少