网站搜索

typescript - 调用对象方法的返回类型注解


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

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

答案#1

目前没有办法正确地获取方法调用的返回类型,因此我的解决方案只是部分的。不过,有一个正在进行中的提案,你可以在这里了解更多信息。

你能做到的最好就是至少从你现在拥有的东西中再多打些字出来。

你可以做的一件事是使用映射类型来获取 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 看起来更简洁。

答案#2

截至 [email ,已添加了映射类型,而在 [email  中添加了条件类型和类型推断。这一个变得非常简单:

type MappedReturnTypes<
    T extends Record<string, (...args: any[]) => any>
> = { [K in keyof T]: ReturnType<T[K]> }

游乐场链接