Typescript 索引签名

156 阅读2分钟

TypeScript 中,索引签名允许定义一个对象,其中可以包含任意数量的属性,这些属性的键可以是任何类型,而值可以是统一的类型。索引签名主要用在接口和类型别名中,以便描述类似于数组或者对象字面量这样的结构。

基本语法

interface IndexSignatureObject {
  [key: string]: valueType;
}
  • key: 索引签名的键名,通常使用 key: string 来表示所有的字符串键,也可以使用 key: number 来表示所有的数字键。
  • valueType: 所有键对应的值的类型。

示例

假设我们有一个对象,它包含了多个用户的信息,每个用户都有一个唯一的ID作为键:

interface User {
  id: number;
  name: string;
  email: string;
}

interface Users {
  [key: string]: User;
}

let users: Users = {
  '1': { id: 1, name: 'Alice', email: 'alice@example.com' },
  '2': { id: 2, name: 'Bob', email: 'bob@example.com' },
};

在这个例子中,Users 接口使用了一个索引签名,允许对象 users 包含任意数量的字符串键,每个键都对应一个 User 类型的对象。

限制条件

  • 一个接口或类型别名中只能有一个索引签名。
  • 如果有多个索引签名,TypeScript 会报错。
  • 索引签名后面的属性将不会被索引签名所覆盖。这意味着,如果一个接口有具体的属性定义,这些属性将优先于索引签名。

只读索引签名

TypeScript 3.7 开始,可以使用 readonly 修饰符来创建只读的索引签名。这意味着不能给对象添加新的属性,但可以修改现有属性的值。

interface ReadonlyArray<T> {
  readonly [index: number]: T;
}

let ro: ReadonlyArray<number> = [1, 2, 3];
ro[0] = 4;  // 允许修改现有属性的值
ro[1] = 5;  // 允许修改现有属性的值
ro[2] = 6;  // 允许修改现有属性的值
ro[3] = 7;  // 错误!不能添加新属性

使用类实现索引签名

在类中,可以使用计算属性名称(使用方括号)来实现索引签名:

class IndexSignatureClass<T> {
  [key: string]: T;
  private data: { [key: string]: T } = {};

  set(key: string, value: T): void {
    this.data[key] = value;
  }

  get(key: string): T | undefined {
    return this.data[key];
  }
}

let classInstance = new IndexSignatureClass<number>();
classInstance.set('one', 1);
console.log(classInstance.get('one'));  // 输出: 1

这个例子中,IndexSignatureClass 类使用了一个索引签名,并且提供了 setget 方法来操作类实例的属性。这样,就可以在运行时动态地添加和访问属性了。