一文读懂TypeScript中的索引签名!

在大多数情况下,我们在使用对象前就可以确定对象的结构,并为对象中的属性添加准确的类型。

但是当我们无法确定对象中有哪些属性时,或者说对象中可以出现任意多个属性时,此时,我们就可以用索引签名类型了。

索引签名,主要是用来规定索引和属性值的类型,索引类型只能是 string 类型 或者 number 类型 或者 symbol 类型。

在 TypeScript 中,索引签名类型包括字符串索引签名类型数字索引签名类型

1. 字符串索引签名类型

1.1. 语法格式

typescript 复制代码
interface MyObj {
  [key: string]: number;
}

上面的这段代码中,使用 [key: string] 来约束该接口中允许出现的属性名称,其中 key 表示字符串索引的标识符,可以是任何有效的属性名,而 number 表示对应属性的值的类型,可以是任意类型。

1.2. 用法

typescript 复制代码
interface MyObj {
  [key: string]: number;
}

let obj: MyObj = {
  a: 1,
  b: 2,
  c: 3,
  d: 4
};

如果对象中属性值的类型不是 number 类型,代码会报错。

typescript 复制代码
interface MyObj {
  [key: string]: number;
}

let obj: MyObj = {
  a: 1,         // 正确
  b: 2,         // 正确
  name: "Echo", // 报错:不能将类型"string"分配给类型"number"
  bool: true,   // 报错:不能将类型"boolean"分配给类型"number"
};

1.3. 特点

  • 一旦定义了索引签名,那么必选属性和可选属性的类型都必须是它的类型的子集。
  • 返回的属性值的类型必须是索引签名指定的类型。
  • 可以与其他明确声明的属性共存。
  • 可以同时拥有多种类型的索引签名。
typescript 复制代码
// Ok
interface Person {
  // 同时拥有 string 类型和 number 类型的索引签名
  [props: string]: string | number;
  // 可以定义其它属性,但是属性值的类型必须是索引签名类型的子集
  // 这里的属性值类型必须是 string 类型或者 number 类型
  name?: string;
  age: number;
}

// Error
interface User {
  [props: string]: string | number;
  name?: string;
  age: number;
  // 报错:类型"true"的属性"bool"不能赋给"string"索引类型"string | number"
  // 由于上面的索引签名规定了只能是 string 类型或者 number 类型,所以这里不能写其它类型
	bool: true;
}
  • 可以访问对象中已存在的属性,如果访问对象中不存在的属性,会返回 undefined
typescript 复制代码
interface Person {
  [props: string]: string | number;
  name: string;
  age: number;
}

const person: Person = {
  name: "Echo",
  age: 26,
  city: "GuangZhou",
  phone: 13000000000,
  gender: "Male",
};

// 访问存在的属性
console.log(person.name);       // 输出:Echo
console.log(person["age"]);     // 输出:26
console.log(person.city);       // 输出:GuangZhou
console.log(person["phone"]);   // 输出:13000000000
console.log(person["gender"]);  // 输出:Male

// 访问不存在的属性
console.log(person["address"]); // 输出:undefined

2. 数字索引签名类型

当一个对象具有数字索引签名时,它意味着该对象可以使用数字来索引并获得相应的属性的值。

2.1. 语法

typescript 复制代码
interface MyArr {
  [index: number]: string
}

上面的这段代码中,我们定义了 MyArr 接口,它具有索引签名。这个索引签名表示了当用 number 去索引 MyArr 时会得到 string 类型的返回值。

2.2. 用法格式

typescript 复制代码
interface MyArr {
  [index: number]: string;
}

const arr: MyArr = ["Echo", "James", "John", "Steven"];
console.log(arr[0]); // Echo
console.log(arr[1]); // James
console.log(arr[2]); // John
console.log(arr[3]); // Steven

2.3. 特点

  • 可以同时拥有多种类型的索引签名。
  • 返回的属性值的类型必须是索引签名指定的类型。
typescript 复制代码
interface MyArr {
  [index: number]: string | number;
}

const arr: MyArr = [1, 'a', 2, 'b'];

3. 注意事项

3.1. 索引签名的键只能是 string、number、symbol 或者模板文本类型

3.2. 不能多次定义相同类型的索引签名

4. 索引签名类型 VS 泛型工具类型Record<K, T>

先看看下面的代码,我们发现索引签名类型和泛型工具类型 Record<K, T> 很相似:

typescript 复制代码
const object1: Record<string, string> = { name: "Echo" };     // 正确
const object2: { [key: string]: string } = { name: "Echo" };  // 正确

但实际上它们两者之间还是有区别的:

4.1. 用途不同

  • 索引签名类型:主要用于定义具有动态属性的对象,允许通过字符串或数字索引来访问属性。
typescript 复制代码
interface MyObj {
  [key: string]: string | number
}

const obj: MyObj = {
  name: "Echo",
  age: 26
}

console.log(obj.name);   // Echo
console.log(obj["age"]); // 26
  • Record<K, T>:主要用于生成一个新的类型,用于表示具有固定类型的属性集合,其中所有属性的值都具有相同的类型。
typescript 复制代码
interface Person {
  name: string;
  gender: string;
}

type NewPerson = Record<keyof Person, string>;
const person: NewPerson = {
  name: "Echo",
  gender: "Male",
}

4.2. 类型约束

  • 索引签名类型:对于索引签名,键的类型可以是 string、number、symbol 或者模板文本类型,值的类型可以是任意类型。
  • Record<K, T>:对于 Record<K, T>,类型参数 K 的类型可以是 string、number 或 symbol,可以接收字面量类型或者字面量类型组成的联合类型来作为参数,而类型参数 T 可以是任意类型。

比如使用联合类型来作为 Key 值:

typescript 复制代码
type Person = Record<"name" | "age" | "gender" | "bool", string | number | boolean>;
const person: Person = {
  name: "Echo",
  age: 26,
  gender: "Male",
  bool: true,
}

5. 总结

以上就是我对 TypeScript 中索引签名的理解,如果有不正确的地方,欢迎大家在评论区多多指正!

看完记得点个赞哦~ 谢谢!🤞🤞🤞

相关推荐
道不尽世间的沧桑1 小时前
第17篇:网络请求与Axios集成
开发语言·前端·javascript
diemeng11192 小时前
AI前端开发技能变革时代:效率与创新的新范式
前端·人工智能
bin91534 小时前
DeepSeek 助力 Vue 开发:打造丝滑的复制到剪贴板(Copy to Clipboard)
前端·javascript·vue.js·ecmascript·deepseek
晴空万里藏片云5 小时前
elment Table多级表头固定列后,合计行错位显示问题解决
前端·javascript·vue.js
曦月合一5 小时前
html中iframe标签 隐藏滚动条
前端·html·iframe
奶球不是球5 小时前
el-button按钮的loading状态设置
前端·javascript
kidding7235 小时前
前端VUE3的面试题
前端·typescript·compositionapi·fragment·teleport·suspense
Σίσυφος19007 小时前
halcon 条形码、二维码识别、opencv识别
前端·数据库
学代码的小前端8 小时前
0基础学前端-----CSS DAY13
前端·css
css趣多多9 小时前
案例自定义tabBar
前端