在ts文档中有一句话:
js实际上会在索引到对象之前将其转换为字符串,也就死说100(number)进行索引与"100"(string)进行索引是一回事,因此两者(两种索引签名)需要保持一致。
在代码中体现为如下
interface objqqq {
[key:string]:string
}
let obj:objqqq={
0:"123",
1:"123",
2:"123"
}
ts环境下代码无报错说明文档所说的确实实现了,也就是number也是“number”字符串,但是一旦作用到数组上便会报错
interface objqqq {
[key:string]:string
}
let arr1:objqqq = ["12","23","34"]
arr1报错,大致意思找不到string类型的key,但当objqqq设置成[key:string]:any时代码又会变成正常,十分奇怪
后来我反应过来,可能是因为数组中的内置属性length的存在导致的,所以又改了一下代码,想验证一下,代码如下
interface objqqq {
[key:string]:number
}
let arr1:objqqq = ["12","23","34"]
let obj:objqqq={
0:"123",
1:"123",
2:"123"
}
更奇怪的事情来了,两者全部报错,obj报错容易理解,因为我设置string类型key值的值为number类型,但是他的值为string类型所以报错,但是奇怪的来了,数组报错变了,不再是找不到stringkey值,而是跟obj报错相同,报错位置在内容,这说明他跟obj一样,虽然上面的类型是stringkey值,但是他通过stringkey找到了数字索引的内容,并且告诉我数组的内容应该是number类型而不是string类型,而上面报错找不到stringkey,可能只是ts不让我这样做,但是我初心未改,我还是想证明length的存在,于是写了下面的代码
interface objqqq {
[key:string]:number
}
let arr1:objqqq = [12,23,34]
继续报错,stringkey找不到,他完全忽视length的存在,接着我继续验证有了下面的代码
interface objqqq {
length:number
}
let arr1:objqqq = [12,23,34]
没有报错,这说明length确实存在啊
为此我到处搜索,搜到了一个名词,叫放宽索引签名,大致意思是,当我设置any是,key值便不会再被验证,于是有了下面的代码
interface objqqq {
[key:number]:any
}
let obj:objqqq={
number:"123",
age:"123",
length:"123"
}
报错,说明并没有放宽,但是当设置stringkey为any时,数组确实被放宽
现象总结
=========================================================================
索引签名类型作用数组时数字类型索引并不会被“ts类型检查”当作字符串类型的键名,即使用字符串类型的数字可以正确的获取到数组内容(仅在数组中,对象中数字类型键名可以被“ts类型检查”当作字符串类型)。
报错
只有当键值为any类型时,数组的数字类型索引才被“ts类型检查”像识别其他数字类型键名一样,也被当成字符串识别。
但这并不代表数字类型索引对应的值,可以逃脱索引签名定义的字符串类型键名的键值的类型检查,也就是说,即使ts不把数字类型索引当作字符串类型键名,但其索引对应的值却受到索引签名中定义的字符串类型键名的键值的类型约束。
报错
数组中内置属性并不会被索引签名识别到,如length
报错,如果识别到内置属性length,则应该满足索引签名
但是在类型中定义属性为length可以识别到。
不报错
在此记录奇怪现象,有大佬看见能解释一下就更好了