TypeScript 如何做索引签名
你有没有过这样的经历?用 JavaScript 写代码时,想声明一个对象,它的键和值都是不确定的——比如一个用户的动态属性,可能是姓名、年龄、地址,也可能是手机号、邮箱,提前写好固定属性总觉得不够灵活,可没了类型约束,又很容易写错键名、传错值。这时候 TypeScript 的索引签名,就能帮你解决这个“灵活与约束难兼顾”的小麻烦。
先搞懂:什么是索引签名?
咱们用生活化的例子来拆解:假设你开了个小卖部的“商品库存本”,这个本子没有固定要写的条目——今天可能记“矿泉水:20瓶”,明天可能加“冰棒:15根”“辣条:30袋”,后天还能加“充电宝:5个”。你不用提前把所有商品都列出来,只要约定好:所有写在本子上的商品(键),都是字符串;对应的数量(值),都是数字。

放到 TypeScript 里,这个“约定”就是索引签名。它允许你声明一个对象,这个对象的键的类型是统一的,值的类型也是统一的,不需要提前把所有键都写死,兼顾了灵活性和类型安全,不会出现“把冰棒的数量写成字符串”这类低级错误。
怎么写索引签名?两步就能上手
索引签名的写法非常直白,就像给对象的键和值定规矩,而且语法也很好记。还是用刚才的小卖部例子,咱们来一步步写:
先定义键和值的类型
第一步,确定你要给对象的键、值定的类型。键一般是字符串(对应生活里的文本条目),也可以是数字(比如用序号当键),值的话根据需求来,比如数字、字符串甚至布尔值都可以。
比如小卖部的例子,键是商品名(字符串),值是库存数(数字),咱们就先定好这俩类型。
用语法写索引签名
TypeScript 里用 [键名: 类型]: 值类型 来写索引签名,把它放在对象类型的声明里就行。完整的小卖部库存类型就是这样:
`typescript
type Inventory = {
// 索引签名:键是字符串,值是数字
[itemName: string]: number;
};
`
你看,itemName 其实就是个占位的名字,你可以换成任何你喜欢的,比如 product 也行,只要后面跟着的类型是键的类型就行。
日常用的小细节,别踩这些坑
索引签名虽然简单,但用的时候有两个小细节要注意,不然容易出错,结合生活例子一看就懂。
第一个细节:如果对象里有固定属性,要和索引签名兼容。
还是小卖部的例子,你想加一个固定属性“总库存”,值是数字,这时候就可以直接写在类型里:
`typescript
type Inventory = {
totalStock: number; // 固定属性
[itemName: string]: number; // 索引签名
};
`
这个时候,你就能用这个类型声明对象了,既可以写固定的 totalStock,也可以加任意的商品键,比如:
`typescript
const myShop: Inventory = {
totalStock: 70, // 固定属性
矿泉水: 20, // 商品条目
冰棒: 15,
辣条: 30,
};
`
这里有个小规则:固定属性的类型,必须能被索引签名的类型兼容。比如如果固定属性 totalStock 是字符串,而索引签名的值是数字,就会报错,就像你给库存本写“总库存:七十”(字符串),又约定所有条目值都是数字,就矛盾了。
第二个细节:索引签名的键只能是 string、number、symbol 这几种。
刚才的例子用的是字符串键,如果你想按序号存商品,比如 1: "矿泉水",那键类型就可以写 number,对应索引签名:
`typescript
type NumberInventory = {
[itemId: number]: string; // 键是数字,值是商品名
};
`
但不能用 boolean 当键,就像你不能给库存本写“true:矿泉水”,这样没实际意义,TypeScript 也不允许这种写法。
举个实用的小场景,加深理解
假设你做了一个简易的通讯录工具,要存朋友的联系方式,每个朋友的联系方式可能是手机号、微信、邮箱,没有固定顺序,也可能随时加新的。用索引签名来做,就能写出类型安全的代码:
`typescript
type ContactBook = {
name: string; // 固定的名字属性
[contactType: string]: string; // 任意联系方式,键是类型(手机号/微信等),值是号码
};
// 符合类型的对象
const myContacts: ContactBook = {
name: "小明",
phone: "138xxxx1234",
wechat: "xiaoming123",
};
`
如果不小心写错,比如把手机号的值写成数字 phone: 138xxxx1234,TypeScript 会直接报错,提醒你值的类型不对,不用等到运行时才发现 bug,这就是索引签名的好处。
是不是不难?核心就是记住:索引签名是给对象的“动态键和值”定统一类型的规则,既不用提前写死所有属性,又能避免类型错误,日常做动态对象的时候用它,就能兼顾灵活和靠谱啦。