为什么我的对象无法添加新属性?
今天在网上看到一个问题,在typescript中定义了一个对象,却无法添加新属性,代码如下:
1 | const obj = {}; |
乍一看到这个问题,我有点疑惑,为什么要这样写呢?我以往的习惯是,需要使用什么类型,都会提前定义好,然后使用就行了,这个类型包括哪些属性,都是提前设置好的。但是这段代码里面的obj
是一个空对象,什么属性都没有,感觉实际应用中这种情况很少。
但是作为一个典型的例子研究一下,还是不错的。这个错误产生的原因是作者对于typescript中的索引签名(index signature
)不熟悉导致的。我们来分析一下原因。
索引签名
typescript在解析obj
的时候,并不知道它里面会有哪些属性,属性的key是什么类型?属性的值又是什么类型?完全不知道,所以当用户试图添加一个新属性的时候,typescript就会报错。
解决的办法也很简单,我们需要提前告知typescript这些关于属性的信息。这个信息就是索引签名
1 | interface looseObject { |
使用Record
类型
这个例子更简单的办法是使用Record
类型,Record
类型在定义特定类型的对象时特别有用。Record<string, any>
表示一个对象类型,其属性名是字符串类型,属性值可以是任意类型。
1 | const obj: Record<string, any> = {}; |
索引签名的使用场景
那么什么场景下需要使用索引签名呢?一般来说,当属性的个数不固定的时候,就需要使用索引签名了。
统计学生成绩
比如要统计学生成绩,每个科目对应一个分数,不同专业的学生科目是不一样的,这时候就可以使用索引签名来定义一个对象类型。
1 | interface StudentScores { |
CSS-In-JS的使用
在CSS-In-JS的场景中,通常需要动态添加样式属性,这时候索引签名也非常有用。下面的代码定义了一个主题(Theme),其中包括color
和spacing
属性,对于color
属性,我们不可能列出所有可能的颜色名称,这时候可以使用索引签名就非常有用了。spacing
也是同样的道理。
1 | type Theme = { |
今天就到这里了,祝大家编程愉快,喜欢就点个关注,我要去打弹弓了,明天见!