浅谈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 相关文章推荐
jquery 实现两Select 标签项互调示例代码
Sep 25 Javascript
Javascript堆排序算法详解
Dec 03 Javascript
JavaScript中的parse()方法使用简介
Jun 12 Javascript
js带缩略图的图片轮播效果代码分享
Sep 14 Javascript
jQuery prototype冲突的2种解决方法(附demo示例下载)
Jan 21 Javascript
javascript获取select标签选中的值
Jun 04 Javascript
Angular-Touch库用法示例
Dec 22 Javascript
简单实现js无缝滚动效果
Feb 05 Javascript
基于Vue实例对象的数据选项
Aug 09 Javascript
react中实现搜索结果中关键词高亮显示
Jul 31 Javascript
JavaScript修改注册表实例代码
Jan 05 Javascript
JS操作JSON常用方法(10w阅读)
Dec 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 输出缓存详解
2009/06/20 PHP
php 将字符串按大写字母分隔成字符串数组
2010/04/30 PHP
迅速确定php多维数组的深度的方法
2014/01/07 PHP
php实现有趣的人品测试程序实例
2015/06/08 PHP
完美利用Yii2微信后台开发的系列总结
2016/07/18 PHP
自制PHP框架之模型与数据库
2017/05/07 PHP
csdn 博客的css样式 v3
2009/02/24 Javascript
JavaScript 异步调用框架 (Part 1 - 问题 &amp; 场景)
2009/08/03 Javascript
JavaScript初学者应注意的七个细节详细介绍
2012/12/27 Javascript
js使用eval解析json(js中使用json)
2014/01/17 Javascript
JavaScript函数定义的常见注意事项小结
2014/09/16 Javascript
javascript实现的简单的表单验证
2015/07/10 Javascript
js实现固定显示区域内自动缩放图片的方法
2015/07/18 Javascript
JavaScript位置与大小(1)之正确理解和运用与尺寸大小相关的DOM属性
2015/12/26 Javascript
Vuejs第十一篇组件之slot内容分发实例详解
2016/09/09 Javascript
H5移动端适配 Flexible方案
2016/10/24 Javascript
React快速入门教程
2017/01/17 Javascript
Vue Cli与BootStrap结合实现表格分页功能
2017/08/18 Javascript
基于jquery实现五星好评
2017/11/18 jQuery
javascript用rem来做响应式开发
2018/01/13 Javascript
ES6下子组件调用父组件的方法(推荐)
2018/02/23 Javascript
JS闭包原理与应用经典示例
2018/12/20 Javascript
js 执行上下文和作用域的相关总结
2021/02/08 Javascript
Python进程间通信Queue实例解析
2018/01/25 Python
Python实现识别图片内容的方法分析
2018/07/11 Python
Python django搭建layui提交表单,表格,图标的实例
2019/11/18 Python
Python+Kepler.gl实现时间轮播地图过程解析
2020/07/20 Python
HTML5如何使用SVG的方法示例
2019/01/11 HTML / CSS
美国知名的时尚购物网站:Anthropologie
2016/12/22 全球购物
教师党员思想汇报
2014/01/06 职场文书
本科应届生求职信
2014/08/05 职场文书
计划生育工作总结2015
2015/04/03 职场文书
穆斯林的葬礼读书笔记
2015/06/26 职场文书
竞聘书的秘诀
2019/04/02 职场文书
pytorch中Schedule与warmup_steps的用法说明
2021/05/24 Python
MySQL触发器的使用
2021/05/24 MySQL