typescript - 打字稿索引签名和方法
问题描述
为什么下面的代码会ts(2411)
出错?
class Greeter {
[key: string]: string | number[];
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet(): string {
return "Hello, " + this.greeting;
}
}
错误是在greet()
which 说type '() => string'
not assignable to type 'string | number[]'
。
object
如果我添加到索引签名,错误就会消失。这是为什么?
同样对于索引签名,它是否使用any
了不好的做法?
Function
编辑:我还在签名中添加了界面。它也有效。不过,问题是为什么。
解决方案
在具有索引签名的类或接口中声明的任何属性或方法必须具有与您在索引中的类型兼容的类型。这就是为什么添加Function
到索引签名会有所帮助。
原因在文档中解释:
虽然字符串索引签名是描述“字典”模式的强大方式,但它们还强制所有属性与其返回类型匹配。这是因为字符串索引声明
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;
}
}
推荐阅读
- scala - 查找databricks错误中所有列的总和
- swift - Vapor 3 - 尝试将登录请求映射到数据库中不存在的模型
- sql - (一个表)获取没有联合的行
- php - Laravel 5.4 - 几个表中的多个关系
- python-3.x - 多处理将 S3 内容主体转换为 pandas DataFrame AWS Sagemaker
- c# - 如何将对象列表从 C# 传递和迭代到 NLua
- javascript - 无法让黑色画布显示在屏幕上
- python - 如何修复“其他”输出超过 1 个结果的问题
- java - 需要在没有xml配置的情况下调用aspect
- c# - 如果 DateTime 为空,如何使用今天的日期?