浅谈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 相关文章推荐
js实现杯子倒水问题自动求解程序
Mar 25 Javascript
jquery 动态创建元素的方式介绍及应用
Apr 21 Javascript
jQuery之按钮组件的深入解析
Jun 19 Javascript
JS中window.open全屏命令解析及使用示例
Dec 11 Javascript
javascript实现rgb颜色转换成16进制格式
Jul 10 Javascript
iframe中使用jquery进行查找的方法【案例分析】
Jun 17 Javascript
React组件的三种写法总结
Jan 12 Javascript
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
Jul 11 Javascript
vue.js实现只弹一次弹框
Jan 29 Javascript
Fetch超时设置与终止请求详解
May 18 Javascript
Vue插件之滑动验证码用法详解
Apr 05 Javascript
jQuery实现简单日历效果
Jul 05 jQuery
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与javascript对多项选择的处理
2006/10/09 PHP
使用PHP实现阻止用户上传成人照片或者裸照
2014/12/25 PHP
让网页根据不同IE版本显示不同的内容
2009/02/08 Javascript
js读取本地excel文档数据的代码
2010/11/11 Javascript
php对mongodb的扩展(小试牛刀)
2012/11/11 Javascript
jquery实现图片上传前本地预览功能
2016/05/10 Javascript
js判断浏览器是否支持严格模式的方法
2016/10/04 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(放大缩小)
2016/12/02 Javascript
原生JS实现ajax与ajax的跨域请求实例
2017/12/01 Javascript
vue环形进度条组件实例应用
2018/10/10 Javascript
vue.js的vue-cli脚手架中使用百度地图API的实例
2019/01/21 Javascript
vue 使用axios 数据请求第三方插件的使用教程详解
2019/07/05 Javascript
layui table数据修改的回显方法
2019/09/04 Javascript
Vue清除定时器setInterval优化方案分享
2020/07/21 Javascript
浅谈vue中get请求解决传输数据是数组格式的问题
2020/08/03 Javascript
[41:17]VG vs Optic 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
Python编程产生非均匀随机数的几种方法代码分享
2017/12/13 Python
matplotlib作图添加表格实例代码
2018/01/23 Python
python实现快速排序的示例(二分法思想)
2018/03/12 Python
配置 Pycharm 默认 Test runner 的图文教程
2018/11/30 Python
对python周期性定时器的示例详解
2019/02/19 Python
python画双y轴图像的示例代码
2019/07/07 Python
python每天定时运行某程序代码
2019/08/16 Python
python实现上传文件到linux指定目录的方法
2020/01/03 Python
Python基于gevent实现高并发代码实例
2020/05/15 Python
基于HTML5实现类似微信手机摇一摇功能(计算摇动次数)
2017/07/24 HTML / CSS
微信小程序canvas实现水平、垂直居中效果
2020/02/05 HTML / CSS
HTML5适合的情人节礼物有纪念日期功能
2021/01/25 HTML / CSS
DNA基因检测和分析:23andMe
2019/05/01 全球购物
办公室主任岗位职责
2013/11/08 职场文书
小学生红领巾广播稿
2014/01/21 职场文书
社区母亲节活动记录
2014/03/06 职场文书
小学生常见病防治方案
2014/06/06 职场文书
2015年加油站站长工作总结
2015/05/27 职场文书
详解MySQL的半同步
2021/04/22 MySQL
python脚本框架webpy模板赋值实现
2021/11/20 Python