浅谈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读取cookie函数代码
Oct 16 Javascript
防止xss和sql注入:JS特殊字符过滤正则
Apr 18 Javascript
jQuery Mobile 导航栏代码
Nov 01 Javascript
JS是按值传递还是按引用传递
Jan 30 Javascript
JS+CSS实现下拉列表框美化效果(3款)
Aug 15 Javascript
原生JS实现拖拽图片效果
Aug 27 Javascript
一波JavaScript日期判断脚本分享
Mar 06 Javascript
js实现加载更多功能实例
Oct 27 Javascript
JS实现的RC4加密算法示例
Aug 16 Javascript
JavaScript中的事件与异常捕获详析
Feb 24 Javascript
js form表单input框限制20个字符,10个汉字代码实例
Apr 12 Javascript
Vue3.0写自定义指令的简单步骤记录
Jun 27 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
PHP DataGrid 实现代码
2009/08/12 PHP
ThinkPHP查询语句与关联查询用法实例
2014/11/01 PHP
PHP冒泡算法详解(递归实现)
2014/11/10 PHP
Firefox+FireBug使JQuery的学习更加轻松愉快
2010/01/01 Javascript
JS字符串处理实例代码
2013/08/05 Javascript
AJAX跨域请求json数据的实现方法
2013/11/11 Javascript
JS实现的一个简单的Autocomplete自动完成例子
2014/04/16 Javascript
JavaScript数据结构与算法之栈详解
2015/03/12 Javascript
jQuery删除一个元素后淡出效果展示删除过程的方法
2015/03/18 Javascript
jquery移动点击的项目到列表最顶端的方法
2015/06/24 Javascript
浅谈javascript中的事件冒泡和事件捕获
2016/12/28 Javascript
Angular 输入框实现自定义验证功能
2017/02/19 Javascript
利用n工具轻松管理Node.js的版本
2017/04/21 Javascript
从setTimeout看js函数执行过程
2017/12/19 Javascript
vue项目中跳转到外部链接的实例讲解
2018/09/20 Javascript
Vue使用vue-recoure + http-proxy-middleware + vuex配合promise实现基本的跨域请求封装
2019/10/21 Javascript
jquery更改元素属性attr()方法操作示例
2020/05/22 jQuery
[01:30]2016国际邀请赛中国区预选赛神秘商店火爆开启
2016/06/26 DOTA
Python实现图片滑动式验证识别方法
2017/11/09 Python
Diango + uwsgi + nginx项目部署的全过程(可外网访问)
2018/04/22 Python
Python3爬虫全国地址信息
2019/01/05 Python
使用 Python 处理 JSON 格式的数据
2019/07/22 Python
Django命名URL和反向解析URL实现解析
2019/08/09 Python
关于PyTorch 自动求导机制详解
2019/08/18 Python
使用Python操作ArangoDB的方法步骤
2020/02/02 Python
浅谈keras 模型用于预测时的注意事项
2020/06/27 Python
Brora官网:英国领先的羊绒服装品牌
2019/08/28 全球购物
麦当劳辞职信范文
2014/01/18 职场文书
抄作业检讨书
2014/02/17 职场文书
安全生产管理合理化建议书
2014/03/12 职场文书
互联网创业计划书写作技巧攻略
2014/03/23 职场文书
创建文明城市标语
2014/06/16 职场文书
治安消防安全责任书
2014/07/23 职场文书
群众路线教育实践活动个人对照检查材料
2014/09/22 职场文书
部门群众路线教育实践活动对照检查材料思想汇报
2014/10/07 职场文书
平凡的世界读书笔记
2015/06/25 职场文书