浅谈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 相关文章推荐
破除网页鼠标右键被禁用的绝招大全
Dec 27 Javascript
javascript IFrame 强制刷新代码
Jul 23 Javascript
获取客户端电脑日期时间js代码(jquery)
Sep 12 Javascript
JavaScript实现twitter puddles算法实例
Dec 06 Javascript
PHP+MySQL+jQuery随意拖动层并即时保存拖动位置实例讲解
Oct 09 Javascript
jQuery常见的选择器及用法介绍
Dec 20 Javascript
React Native中Navigator的使用方法示例
Oct 13 Javascript
security.js实现的RSA加密功能示例
Jun 06 Javascript
vue swipe自定义组件实现轮播效果
Jul 03 Javascript
vue 实现setInterval 创建和销毁实例
Jul 21 Javascript
小程序实现点击tab切换左右滑动
Nov 16 Javascript
详解如何使用Node.js实现热重载页面
May 06 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基于CURL进行POST数据上传实例
2014/11/10 PHP
PHP原生函数一定好吗?
2014/12/08 PHP
php导入模块文件分享
2015/03/17 PHP
JavaScript iframe的相互操作浅析
2009/10/14 Javascript
JQuery动态创建DOM、表单元素的实现代码
2011/08/09 Javascript
基于jQuery实现的百度导航li拖放排列效果,即时更新数据库
2012/07/31 Javascript
Javascript连接多个数组不用concat来解决
2014/03/24 Javascript
JsRender实用入门教程
2014/10/31 Javascript
jQuery实现表格行上下移动和置顶效果
2015/06/05 Javascript
JavaScript检查数字是否为整数或浮点数的方法
2015/06/09 Javascript
javascript实现继承的简单实例
2015/07/26 Javascript
详解vue.js组件化开发实践
2016/12/14 Javascript
详解jQuery uploadify文件上传插件的使用方法
2016/12/16 Javascript
微信小程序修改数组长度的问题的解决
2019/12/17 Javascript
js实现多个标题吸顶效果
2020/01/08 Javascript
基于Ionic3实现选项卡切换并重新加载echarts
2020/09/24 Javascript
[06:06]2018DOTA2亚洲邀请赛主赛事第四日战况回顾 全明星赛欢乐上演
2018/04/07 DOTA
深入解析Python中的list列表及其切片和迭代操作
2016/03/13 Python
Python数据操作方法封装类实例
2017/06/23 Python
Python+Socket实现基于TCP协议的客户与服务端中文自动回复聊天功能示例
2017/08/31 Python
Python3一行代码实现图片文字识别的示例
2018/01/15 Python
python如何去除字符串中不想要的字符
2020/07/05 Python
python实现时间序列自相关图(acf)、偏自相关图(pacf)教程
2020/06/03 Python
使用ITK-SNAP进行抠图操作并保存mask的实例
2020/07/01 Python
python如何绘制疫情图
2020/09/16 Python
历史教育专业个人求职信
2013/12/13 职场文书
电脑租赁公司创业计划书
2014/01/08 职场文书
学校春季防火方案
2014/06/08 职场文书
教师求职信
2014/06/17 职场文书
行政管理专业求职信
2014/07/06 职场文书
竞聘演讲稿开场白
2014/08/25 职场文书
2015暑期爱心支教策划书
2015/07/14 职场文书
适合毕业生创业的项目怎么找?
2019/08/08 职场文书
Python django中如何使用restful框架
2021/06/23 Python
Python安装使用Scrapy框架
2022/04/12 Python
MySQL 条件查询的常用操作
2022/04/28 MySQL