TypeScript索引签名

TypeScript索引签名,JavaScript支持使用索引去访问对象的属性,即通过方括号“[]”语法去访问对象属性。一个典型的例子是数组对象,我们既可以使用数字索引去访问数组元素,也可以使用字符串索引去访问数组对象上的属性和方法。示例如下:

const colors = ['red', 'green', 'blue'];

// 访问数组中的第一个元素
const red = colors[0];

// 访问数组对象的length属性
const len = colors['length'];

接口中的索引签名能够描述使用索引访问的对象属性的类型。索引签名只有以下两种:

  • 字符串索引签名。
  • 数值索引签名。

字符串索引签名

字符串索引签名的语法如下所示:

[IndexName: string]: Type

在该语法中,IndexName表示索引名,它可以为任意合法的标识符。索引名只起到占位的作用,它不代表真实的对象属性名;在字符串索引签名中,索引名的类型必须为string类型;Type表示索引值的类型,它可以为任意类型。示例如下:

interface A {
   [prop: string]: number;
}

一个接口中最多只能定义一个字符串索引签名。字符串索引签名会约束该对象类型中所有属性的类型。例如,下例中的字符串索引签名定义了索引值的类型为number类型。那么,该接口中所有属性的类型必须能够赋值给number类型。

interface A {
   [prop: string]: number;

   a: number;
   b: 0;
   c: 1 | 2;
}

此例中,属性abc的类型都能够赋值给字符串索引签名中定义的number类型,因此不会产生错误。接下来,我们再来看一个错误的例子:

interface B {
   [prop: string]: number;

   a: boolean;      // 编译错误
   b: () => number; // 编译错误
   c(): number;     // 编译错误
}

此例中,字符串索引签名中定义的索引值类型依旧为number类型。属性a的类型为boolean类型,它不能赋值给number类型,因此产生编译错误。属性b和方法c的类型均为函数类型,不能赋值给number类型,因此也会产生编译错误。

数值索引签名

数值索引签名的语法如下所示:

[IndexName: number]: Type

在该语法中,IndexName表示索引名,它可以为任意合法的标识符。索引名只起到占位的作用,它不代表真实的对象属性名;在数值索引签名中,索引名的类型必须为number类型;Type表示索引值的类型,它可以为任意类型。

interface A {
   [prop: number]: string;
}

一个接口中最多只能定义一个数值索引签名。数值索引签名约束了数值属性名对应的属性值的类型。

interface A {
   [prop: number]: string;
}

const obj: A = ['a', 'b', 'c'];

obj[0];  // string

若接口中同时存在字符串索引签名和数值索引签名,那么数值索引签名的类型必须能够赋值给字符串索引签名的类型。因为在JavaScript中,对象的属性名只能为字符串(或Symbol)。虽然JavaScript也允许使用数字等其他值作为对象的索引,但最终它们都会被转换为字符串类型。因此,数值索引签名能够表示的属性集合是字符串索引签名能够表示的属性集合的子集。

下例中,字符串索引签名的类型为number类型,数值索引签名的类型为数字字面量联合类型“0 | 1”。由于“0 | 1”类型能够赋值给number类型,因此该接口定义是正确的。示例如下:

interface A {
   [prop: string]: number;
   [prop: number]: 0 | 1;
}

但如果我们交换字符串索引签名和数值索引签名的类型,则会产生编译错误。示例如下:

interface A {
   [prop: string]: 0 | 1;
   [prop: number]: number; // 编译错误
}

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!