我有一个数组,我想通过添加属性将其重新用作对象。
const arr = ["Hi", "my", "name", "is"];
arr.name = "Peter";
在TypeScript中,可以使用索引签名来键入。为了涵盖数字索引和字符串索引,我使用了更通用的字符串索引签名。但是,在尝试将数组分配给接口时,TypeScript会出现错误。
interface StringArray {
[index: string]: string | number;
}
const arr: StringArray = ["Hi", "my", "name", "is"];
// Type 'string[]' is not assignable to type 'StringArray'.
// Index signature is missing in type 'string[]'.(2322)
arr.name = "Peter";
我在字符串索引签名中包含了number
类型,使得arr.length
也被覆盖。
我的理由如下。在JavaScript中,括号属性访问器中的数字索引被转换为字符串,即arr[0]
被转换为arr["0"]
。考虑到这一点,我希望字符串索引签名是数字索引签名的超集,这样它就涵盖了所有的数字索引以及字符串索引。
换言之,如果以下内容有效
interface NumbersArray {
[index: number]: number;
}
const arr: NumbersArray = [10, 20, 30];
那么这也应该起作用(它不起作用(
interface NumbersArray {
[index: string]: number;
}
const arr: NumbersArray = [10, 20, 30];
// Type 'number[]' is not assignable to type 'StringArray'.
// Index signature is missing in type 'number[]'.(2322)
甚至手册中也指出,数字索引签名的类型必须是字符串索引签名的子类型,正是因为这个原因。
从数字索引器返回的类型必须是从字符串索引器返回类型的子类型。
所以我的问题归结为以下几点。
当字符串索引是数字索引的超集时,为什么数组在TypeScript中没有字符串索引签名?
PS。我不想在数组上使用as any
这样的类型断言来规避类型检查。请不要建议使用类型断言。
数组类型在设计上不能有字符串索引:
interface Array<T> {
length: number;
[x: number]: T;
// Other members
}
不要混淆索引值的类型和索引的类型。
在类型论中,索引类型是一种类型构造函数。在这种情况下,它是根据索引值的类型(number
或string
(构建的。
string
和number
是不相关的类型,但数字索引的类型IndexType<number>
是一个子类型由于IndexType<string>
的工作方式,javascript索引:可以使用数字索引值n
作为访问CCD_ 14元素的字符串索引CCD_。
如果您想要的对象是一个数组,并且具有未知数量的属性,请使用交叉点类型。
字符串对象的数组,具有字符串类型的附加属性:
type StringArrayExt = Array<string> & { [index: string]: string };
let arr = ['Hi', 'my', 'name', 'is'] as StringArrayExt;
arr.name = 'Peter';