尝试为我的接口对象分配值(如果它具有相似的键)?

时间:2018-10-23 17:38:39

标签: javascript angular typescript

我收到的数据需要映射到我为对象分配键时为响应声明的接口,该接口显示错误TS7017: Element implicitly has an 'any' type because type 'Idetails' has no index signature.,有什么解决的办法吗?

main.ts

public Responsehandler(@Body() data: any): any {
    const response: Idetails = {} as Idetails;
    if (data.details === undefined || data.details === null) {
        return data;
    }
    if (data.details) {
        response.details.lineOfBusiness = "PBM";
        Object.keys(data.details).forEach((key) => {
            response.details[key] = data.details[key]
        });
    }
    return response;
}

interface.ts

export interface Idetails {
 primary:balanceDetails;
 secondary: balanceDetails;
}

export interface balanceDetails {
     beginningBalance: string;
     endingBalance: string;
}

1 个答案:

答案 0 :(得分:1)

我猜想您正在遇到Object.keys(obj)返回string[]而不是(keyof typeof obj)[]之类的问题。这是一个common issuereported一个lotObject.keys()必须返回string[]的原因是因为TypeScript中的类型是 open ,也就是说,对象必须至少具有 描述的属性匹配的类型。因此,唯一的类型安全返回值是string[]。有关更多信息,请参见this comment

这意味着假设data.details的类型为Idetails(我看不到您的代码... data的类型仅为any;您应该进一步说明),您所知道的就是它至少具有{em> primarysecondary属性,但可能还有更多。例如,data.details可能是

const details = {
  primary: { beginningBalance: "$0", endingBalance: "$200" },
  secondary: { beginningBalance: "25¢", endingBalance: "10¢" },
  tertiary: { beginningBalance: "₿100,000", endingBalance: "₿0.001" }
}

因此key并不是response.details的有效索引,因为key可能是"teritary"


最简单的处理方法是assert Object.keys(data.details)仅返回您知道的密钥。当然,有可能在运行时会有额外的键,并且代码会将这些额外的属性仅复制到response.details ...这可能是无害的,因为它不会阻止response.details成为有效的Idetails。这是您的操作方法:

(Object.keys(data.details) as (keyof Idetails)[]).forEach((key) => {
  response.details[key] = data.details[key]; // okay
});

请注意,我们正在使用as关键字来断言Object.keys(data.details)返回了(keyof Idetails)[]。现在,将key推断为"primary" | "secondary",并且编译器对分配感到满意。


在要防止复制额外属性的情况下,还有其他方法可以解决此问题,例如,手动指定要复制的键的数组而无需完全检查data.details

// helper function to narrow array to string literals
const stringLiterals = <T extends string[]>(...args: T) => args;

// stringLiterals("primary", "secondary") is inferred as type ["primary", "secondary"]
stringLiterals("primary", "secondary").forEach((key) => {
  response.details[key] = data.details[key]; // okay
});

现在这是完全类型安全的,不需要任何类型声明,但是可能比它值得的麻烦更多。


希望有所帮助;祝你好运!