在具有索引签名的类或接口中声明的任何属性或方法的类型必须与您在索引中的类型兼容。这就是为什么在索引签名中添加Function 会有所帮助。
原因是explained in the documentation:
虽然字符串索引签名是描述
“字典”模式,它们还强制所有属性匹配
他们的返回类型。这是因为字符串索引声明
obj.property 也可用作 obj["property"]。在下面的
例如,名称的类型与字符串索引的类型不匹配,并且
类型检查器给出错误:
interface NumberDictionary {
[index: string]: number;
length: number; // ok, length is a number
name: string; // error, the type of 'name' is not a subtype of the indexer
}
将any 添加到索引器签名可能被认为是一种不好的做法,
因为any 禁止类型检查,并且从any 以任何方式获得的任何值也具有any 类型,除非另有明确声明,因此any 会增加您遇到编译器未报告的类型错误的机会。
在类型中添加Function 更好,因为它正确地描述了类中包含的实际数据——当您使用索引访问来获取这样的值时
const key = 'greeting';
const value = this[key];
如果key 恰好等于'greet',您可能会得到一个函数作为值。此外,当您将字符串值分配给 greet:
this['greet'] = 'hi!';
该方法将被字符串值覆盖,您将无法再调用它。
考虑到所有这些,最好将带有索引签名的字典保存在类的单独属性中,而不是类本身中。像这样的东西可以工作:
class Greeter {
data: { [key: string]: string | number[] } = {};
get greeting(): string { return this.data.greeting.toString() }
set greeting(value: string) { this.data.greeting = value };
constructor(message: string) {
this.greeting = message;
}
greet(): string {
return "Hello, " + this.greeting;
}
}