首页 > 解决方案 > TypeScript - ts(7053):元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引

问题描述

在 TypeScript 中,我声明了一个这样的接口:

export default interface MyDTO {
    readonly num: string;
    readonly entitle: string;
    readonly trb: string;
    readonly ucr: string;
    readonly dcr: string;
    readonly udm?: string;
    readonly ddm?: string;
}

使用函数,我想访问属性的值,其名称包含在变量中。

private doSomething(dto: MyDTO, property: string): any {
    let label: any;

    if (['dcr', 'ddm'].includes(property)) {
        label = doSomethingElse(dto[property]);
    } else {
        label = dto[property];
    }
    
    return label;
}

不幸的是,TypeScript 给了我以下错误信息:

元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型“MyDTO”。在类型“MyDTO”.ts(7053) 上找不到带有“字符串”类型参数的索引签名

有人有想法吗?

谢谢

标签: javascripttypescriptinterface

解决方案


这样做的原因是因为MyDTO已经明确命名了属性,但是您使用通用字符串作为索引,所以 TypeScript 说它不能保证传递给您的doSomething函数的任何字符串实际上都会匹配您界面上的属性名称.

TypeScript 2.1 中引入的一个很好的解决方法是 keyof. 这使您可以显式键入某些内容作为某个类/接口的键。

这将 A. 摆脱您看到的 TS 错误,并且 B. 还将检查以确保您的函数的任何调用者实际上传递了一个有效的密钥。

export default interface MyDTO {
    readonly num: string;
    readonly entitle: string;
    readonly trb: string;
    readonly ucr: string;
    readonly dcr: string;
    readonly udm?: string;
    readonly ddm?: string;
}

function doSomething(dto: MyDTO, property: keyof MyDTO): any {
    let label: any;

    if (['dcr', 'ddm'].includes(property)) {
        label = doSomethingElse(dto[property]);
    } else {
        label = dto[property];
    }
    
    return label;
}

doSomething(obj, "foo") // is a TS error
doSomething(obj, "num") // is valid

推荐阅读