返回具有相同属性名称的类型

时间:2018-02-16 17:42:14

标签: typescript generics

我希望函数返回一个与泛型类型参数类型具有相同属性名称的类型。

我试过了:

function getObjectInfo<T>(obj: T): { [key: keyof T]: any; }  {
    const info = {};
    Object.getOwnPropertyNames(obj).forEach(propertyName => {
        info[propertyName] = { /* some info object */ };
    });
    return info;
}

function getObjectInfo<T, K extends keyof T>(obj: T): { [key: K]: any; }  {
    const info = {};
    Object.getOwnPropertyNames(obj).forEach(propertyName => {
        info[propertyName] = { /* some info object */ };
    });
    return info;
}

但是收到以下错误

  

索引签名参数类型不能是联合类型。请考虑使用映射对象类型。

更新

也尝试过:

function getObjectInfo<T extends { [key: string]: any }, K extends keyof T>(obj: T): { [key: K]: any; }  {
    const info = {};
    Object.getOwnPropertyNames(obj).forEach(propertyName => {
        info[propertyName] = { /* some info object */ };
    });
    return info;
}

所以K不是联合类型但仍然会得到相同的错误

1 个答案:

答案 0 :(得分:2)

正如错误所述,您可以考虑使用映射对象来执行此操作。映射对象将使用语法[key in keyof T]而不是[key: keyof T],并将这些键映射到您指定的任何类型(在您的情况下为any)。

以下是您的代码段的外观。唯一的变化是返回类型:

function getObjectInfo<T>(obj: T): { [key in keyof T]: any; } {
    const info = {};
    Object.getOwnPropertyNames(obj).forEach(propertyName => {
        info[propertyName] = { /* some info object */ };
    });
    return info;
}

const x = getObjectInfo({foo: "bar"}); // x has type {foo: any}

此外,您可以使用内置的Record类型作为另一种解决方案。 Record类型接受两个通用参数。第一个是表示记录键的字符串联合,第二个是它们映射到的类型。因此,对于相同的结果,上述返回类型也可以替换为Record<keyof T, any>