浅谈TypeScript 索引签名的理解


Posted in Javascript onOctober 16, 2021

我们用两个对象来描述两个码农的工资:

const salary1 = {
  baseSalary: 100_000,
  yearlyBonus: 20_000
};
 
const salary2 = {
  contractSalary: 110_000
};

然后写一个获取总工资的函数

function totalSalary(salaryObject: ???) {
  let total = 0;
  for (const name in salaryObject) {
    total += salaryObject[name];
  }
  return total;
}
totalSalary(salary1); // => 120_000
totalSalary(salary2); // => 110_000

如果是你的,要如何声明totalSalary()函数的salaryObject参数,以接受具有字符串键和数字值的对象?

答案是使用一个索引签名!

接着,我们来看看什么是 TypeScript 索引签名以及何时需要它们。

1.什么是索引签名

索引签名的思想是在只知道键和值类型的情况下对结构未知的对象进行类型划分。

它完全符合salary参数的情况,因为函数应该接受不同结构的salary对象,唯一的要求是属性值为数字。

我们用索引签名来声明salaryObject参数

function totalSalary(salaryObject: { [key: string]: number }) {
  let total = 0;
  for (const name in salaryObject) {
    total += salaryObject[name];
  }
  return total;
}
 
totalSalary(salary1); // => 120_000
totalSalary(salary2); // => 110_000

{[key: string]: number} 是索引签名,它告诉TypeScript salaryObject 必须是一个以string 类型为键,以 number 类型为值的对象。

2. 索引签名语法

索引签名的语法相当简单,看起来与属性的语法相似,但有一点不同。我们只需在方括号内写上键的类型,而不是属性名称:{ [key: KeyType]: ValueType }。

下面是一些索引签名的例子。

string 类型是键和值。

interface StringByString {
  [key: string]: string;
}
 
const heroesInBooks: StringByString = {
  'Gunslinger': '前端小智',
  'Jack Torrance': '王大志'
};

string 类型是键,值可以是 stringnumberboolean

interface Options {
  [key: string]: string | number | boolean;
  timeout: number;
}
 
const options: Options = {
  timeout: 1000,
  timeoutMessage: 'The request timed out!',
  isFileUpload: false
};

签名的键只能是一个 string`、numbersymbol`。其他类型是不允许的。

浅谈TypeScript 索引签名的理解

3. 索引签名的注意事项

TypeScript中的索引签名有一些注意事项,需要注意。

3.1不存在的属性

如果试图访问一个索引签名为 { [key: string]: string } 的对象的一个不存在的属性,会发生什么?

正如预期的那样,TypeScript 将值的类型推断为 string。但是检查运行时值,它是undefined:

浅谈TypeScript 索引签名的理解

根据 TypeScript 提示, value变量是一个 string 类型,但是它的运行时值是 undefined

索引签名只是将一个键类型映射到一个值类型,仅此而已。如果没有使这种映射正确,值类型可能会偏离实际的运行时数据类型。

为了使输入更准确,将索引值标记为 string undefined。这样,TypeScript就会意识到你访问的属性可能不存在

浅谈TypeScript 索引签名的理解

3.2 string 和 number 键

假设有一个数字名称的字典:

interface NumbersNames {
  [key: string]: string
}
 
const names: NumbersNames = {
  '1': 'one',
  '2': 'two',
  '3': 'three',
  // ...
};

浅谈TypeScript 索引签名的理解

不会,正常工作。

当在属性访问器中作为键使用时,JavaScript隐式地将数字强制为字符串(names[1]names['1']相同)。TypeScript也会执行这个强制。

你可以认为 [key: string] 与 [key: string | number] 相同。

4.索引签名与 Record<Keys, Type>对比

TypeScript有一个实用类型 Record<Keys, Type>,类似于索引签名。

const object1: Record<string, string> = { prop: 'Value' }; // OK
const object2: { [key: string]: string } = { prop: 'Value' }; // OK

那问题来了...什么时候使用 Record<Keys, Type>,什么时候使用索引签名?乍一看,它们看起来很相似

我们知道,索引签名只接受 stringnumber symbol 作为键类型。如果你试图在索引签名中使用,例如,字符串字面类型的联合作为键,这是一个错误。

浅谈TypeScript 索引签名的理解

索引签名在键方面是通用的。

但是我们可以使用字符串字面值的联合来描述 Record<keys, Type>中的键

type Salary = Record<'yearlySalary'|'yearlyBonus', number>
 
const salary1: Salary = { 
  'yearlySalary': 120_000,
  'yearlyBonus': 10_000
}; // OK

Record<Keys, Type> 是为了具体到键的问题。

建议使用索引签名来注释通用对象,例如,键是字符串类型。但是,当你事先知道键的时候,使用Record<Keys, Type>来注释特定的对象,例如字符串字面量' prop1' | 'prop2'被用于键值。

 总结:

如果你不知道你要处理的对象结构,但你知道可能的键和值类型,那么索引签名就是你需要的。

索引签名由方括号中的索引名称及其类型组成,后面是冒号和值类型: { [indexName: KeyType]: ValueType }, KeyType 可以是一个 stringnumber symbol,而ValueType 可以是任何类型。

到此这篇关于浅谈TypeScript 索引签名的理解的文章就介绍到这了,更多相关TypeScript 索引签名内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
Javascript !!的作用
Dec 04 Javascript
jquery对ajax的支持介绍
Dec 10 Javascript
JS面向对象(3)之Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
Feb 25 Javascript
第一次动手实现bootstrap table分页效果
Sep 22 Javascript
js实现方块上下左右移动效果
Aug 17 Javascript
Angular js 实现添加用户、修改密码、敏感字、下拉菜单的综合操作方法
Oct 24 Javascript
JS实现的视频弹幕效果示例
Aug 17 Javascript
js中this的指向问题归纳总结
Nov 28 Javascript
小程序如何自主实现拦截器的示例代码
Nov 04 Javascript
JS控制只能输入数字并且最多允许小数点两位
Nov 24 Javascript
vue项目打包之开发环境和部署环境的实现
Apr 23 Javascript
Vue实现图书管理案例
Jan 20 Vue.js
JavaScript 反射学习技巧
Oct 16 #Javascript
JS的深浅复制详细
Oct 16 #Javascript
JS 基本概念详细介绍
Oct 16 #Javascript
AJAX实现指定部分页面刷新效果
AJAX实现省市县三级联动效果
Oct 16 #Javascript
简单聊聊Vue中的计算属性和属性侦听
Oct 05 #Vue.js
JS中如何优雅的使用async await详解
Oct 05 #Javascript
You might like
DOTA2 玩家自创拉野攻略 特色英雄快速成长篇
2020/04/20 DOTA
生成php程序的php代码
2008/04/07 PHP
CI框架实现框架前后端分离的方法详解
2016/12/30 PHP
PHP实现的文件浏览器功能简单示例
2019/09/12 PHP
JQuery 表格操作(交替显示、拖动表格行、选择行等)
2009/07/29 Javascript
JS 中document.URL 和 windows.location.href 的区别
2009/11/11 Javascript
用Juery网页选项卡实现代码
2011/06/13 Javascript
JavaScript操作XML 使用百度RSS作为新闻源示例
2012/02/17 Javascript
javascript时间自动刷新实现原理与步骤
2013/01/06 Javascript
js实现表单Radio切换效果的方法
2015/08/17 Javascript
Ext JS动态加载JavaScript创建窗体的方法
2016/06/23 Javascript
yarn与npm的命令行小结
2016/10/20 Javascript
如何使用Vuex+Vue.js构建单页应用
2016/10/27 Javascript
JS排序之冒泡排序详解
2017/04/08 Javascript
JavaScript 获取元素在父节点中的下标(推荐)
2017/06/28 Javascript
vuejs项目打包之后的首屏加载优化及打包之后出现的问题
2018/04/01 Javascript
node.js中对Event Loop事件循环的理解与应用实例分析
2020/02/14 Javascript
详解使用mocha对webpack打包的项目进行&quot;冒烟测试&quot;的大致流程
2020/04/27 Javascript
Python判断值是否在list或set中的性能对比分析
2016/04/16 Python
python实现汉诺塔递归算法经典案例
2021/03/01 Python
浅谈Python中用datetime包进行对时间的一些操作
2016/06/23 Python
Pytorch实现GoogLeNet的方法
2019/08/18 Python
在tensorflow中实现去除不足一个batch的数据
2020/01/20 Python
安装Anaconda3及使用Jupyter的方法
2020/10/27 Python
耐克中国官方商城:Nike中国
2018/10/18 全球购物
大学生实习期自我评价范文
2013/10/03 职场文书
护士自我鉴定
2013/10/23 职场文书
个人承诺书
2014/03/26 职场文书
安全承诺书格式
2014/05/21 职场文书
小学生勤俭节约演讲稿
2014/08/28 职场文书
小区门卫的岗位职责
2014/09/26 职场文书
领导四风问题整改措施思想汇报
2014/10/13 职场文书
党的群众路线学习笔记
2014/11/06 职场文书
2015年财务科工作总结范文
2015/05/13 职场文书
python OpenCV学习笔记
2021/03/31 Python
Python 详解通过Scrapy框架实现爬取百度新冠疫情数据流程
2021/11/11 Python