浅谈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 相关文章推荐
图片onload事件触发问题解决方法
Jul 31 Javascript
javascript 另一种图片滚动切换效果思路
Apr 20 Javascript
Jquery利用mouseenter和mouseleave实现鼠标经过弹出层且可以点击
Feb 12 Javascript
JS操作CSS随机改变网页背景实现思路
Mar 10 Javascript
Node.js文件操作详解
Aug 16 Javascript
jquery.cookie.js使用指南
Jan 05 Javascript
jQuery超酷平面式时钟效果代码分享
Mar 30 Javascript
jquery用ajax方式从后台获取json数据后如何将内容填充到下拉列表
Aug 26 Javascript
小程序实现发表评论功能
Jul 06 Javascript
Javascript和jquery在selenium的使用过程
Oct 31 jQuery
vue实现拖拽效果
Dec 23 Javascript
JavaScript点击按钮生成4位随机验证码
Jan 28 Javascript
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之COOKIE支持详解
2010/09/20 PHP
PHP实现创建一个RPC服务操作示例
2020/02/23 PHP
PHP isset empty函数相关面试题及解析
2020/12/11 PHP
checkbox全选/取消全选以及checkbox遍历jQuery实现代码
2009/12/02 Javascript
JS 面向对象之神奇的prototype
2011/02/26 Javascript
js获取图片大小的函数代码
2011/09/20 Javascript
jQuery实现瀑布流布局
2014/12/12 Javascript
浅谈 javascript 事件处理
2015/01/04 Javascript
javascript:void(0)点击登录没反应怎么解决
2015/11/13 Javascript
IE下JS保存图片的简单实例
2016/07/15 Javascript
基于AngularJS实现iOS8自带的计算器
2016/09/12 Javascript
JS中常用的正则表达式
2016/09/29 Javascript
Three.js利用顶点绘制立方体的方法详解
2017/09/27 Javascript
bootstrap时间插件daterangepicker使用详解
2017/10/19 Javascript
Vuex提升学习篇
2018/01/11 Javascript
Vue2.5通过json文件读取数据的方法
2018/02/27 Javascript
小程序如何在不同设备上自适应生成海报的实现方法
2019/08/20 Javascript
基于Element封装一个表格组件tableList的使用方法
2020/06/29 Javascript
[55:39]DOTA2-DPC中国联赛 正赛 VG vs LBZS BO3 第二场 1月19日
2021/03/11 DOTA
分享一个可以生成各种进制格式IP的小工具实例代码
2017/07/28 Python
OpenCV搞定腾讯滑块验证码的实现代码
2019/05/18 Python
Python3使用xml.dom.minidom和xml.etree模块儿解析xml文件封装函数的方法
2019/09/23 Python
Tensorflow的梯度异步更新示例
2020/01/23 Python
Tensorflow实现多GPU并行方式
2020/02/03 Python
基于Python计算圆周率pi代码实例
2020/03/25 Python
python中的unittest框架实例详解
2021/02/05 Python
LocalStorage记住用户和密码功能
2017/07/24 HTML / CSS
C#面试题
2016/05/06 面试题
园林技术个人的自我评价
2014/01/08 职场文书
法律专业学生的自我评价
2014/02/07 职场文书
我爱我家教学反思
2014/05/01 职场文书
文明美德伴我成长演讲稿
2014/05/12 职场文书
开展党的群众路线教育实践活动工作总结
2014/11/05 职场文书
运动会新闻报道稿
2015/07/22 职场文书
自从在 IDEA 中用了热部署神器 JRebel 之后,开发效率提升了 10(真棒)
2021/06/26 Java/Android
Linux中sftp常用命令整理
2022/06/28 Servers