TypeScript-ts(7053):元素隐式具有"any"类型,因为类型"string"的表达式不能用于索引

TypeScript-ts(7053):元素隐式具有

问题描述:

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

In TypeScript, I declare an interface like this:

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

我想使用一个函数来访问属性的值,该属性的名称包含在变量中.

With a function, I would like to access the value of a property, whose name is contained in a variable.

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给我以下错误消息:

Unfortunately, TypeScript gives me the following error message :

元素隐式地具有"any"类型,因为类型的表达式 字符串"不能用于索引类型"MyDTO".没有索引签名 在类型上发现参数类型为字符串"的字符串 'MyDTO'.ts(7053)

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'MyDTO'. No index signature with a parameter of type 'string' was found on type 'MyDTO'.ts(7053)

有人有主意吗?

谢谢

其原因是因为MyDTO具有显式命名的属性,但是您使用的是通用字符串作为索引,因此TypeScript表示可以不能保证传递给doSomething函数的任何字符串实际上都将与您界面上的属性名称匹配.

The reason for this is because MyDTO has explicitly named properties, but you're using a generic string as an index, so TypeScript is saying that it can't guarantee that whatever string is passed into your doSomething function will actually match a property name on your interface.

在TypeScript 2.1中引入的一个很好的解决方法是keyof.这样,您就可以明确地键入某些内容作为某个类/接口的键.

An excellent workaround for this that was introduced in TypeScript 2.1 is keyof. This allows you to explicitly type something as a key of a certain class/interface.

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

This will A. get rid of the TS error you're seeing, and B. also check to make sure that any callers of your function actually pass a valid key.

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