在 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 类使用了一个索引签名,并且提供了 set 和 get 方法来操作类实例的属性。这样,就可以在运行时动态地添加和访问属性了。