浅谈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 prototype属性使用说明
May 13 Javascript
jquery里的正则表达式说明
Aug 03 Javascript
IE与FireFox中的childNodes区别
Oct 20 Javascript
css配合jquery美化 select
Nov 29 Javascript
配置Grunt的Task时通配符支持和动态生成文件名问题
Sep 06 Javascript
Javascript 事件冒泡机制详细介绍
Oct 10 Javascript
javascript 实现动态侧边栏实例详解
Nov 11 Javascript
jQuery实现花式轮播之圣诞节礼物传送效果
Dec 25 Javascript
node.js平台下利用cookie实现记住密码登陆(Express+Ejs+Mysql)
Apr 26 Javascript
Vue.directive 自定义指令的问题小结
Mar 04 Javascript
浅谈Vue SSR中的Bundle的具有使用
Nov 21 Javascript
vue中实现图片压缩 file文件的方法
May 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获取网页标题的3种实现方法代码实例
2014/04/11 PHP
JavaScript面向对象(极简主义法minimalist approach)
2012/07/17 Javascript
js数值计算时使用parseInt进行数据类型转换(jquery)
2014/10/07 Javascript
基于jquery实现页面滚动到底自动加载数据的功能
2015/12/19 Javascript
Flow之一个新的Javascript静态类型检查器
2015/12/21 Javascript
点击页面任何位置隐藏div的实现方法
2016/09/05 Javascript
使用JSON作为函数的参数的优缺点
2016/10/27 Javascript
对vue.js中this.$emit的深入理解
2018/02/23 Javascript
webpack4 入门最简单的例子介绍
2018/09/05 Javascript
NodeJs实现简单的爬虫功能案例分析
2018/12/05 NodeJs
微信小程序--获取用户地理位置名称(无须用户授权)的方法
2019/04/29 Javascript
[32:17]完美世界DOTA2联赛循环赛LBZS vs Forest第二场 10月30日
2020/10/31 DOTA
Python高效编程技巧
2013/01/07 Python
让python同时兼容python2和python3的8个技巧分享
2014/07/11 Python
python私有属性和方法实例分析
2015/01/15 Python
python实现在sqlite动态创建表的方法
2015/05/08 Python
Python简单格式化时间的方法【strftime函数】
2016/09/18 Python
python实现两个dict合并与计算操作示例
2019/07/01 Python
Django 导出项目依赖库到 requirements.txt过程解析
2019/08/23 Python
关于ZeroMQ 三种模式python3实现方式
2019/12/23 Python
Python键鼠操作自动化库PyAutoGUI简介(小结)
2020/05/17 Python
python装饰器实现对异常代码出现进行自动监控的实现方法
2020/09/15 Python
使用HTML5和CSS3表单验证功能
2017/05/05 HTML / CSS
美国学校用品、教室和教学商店:Discount School Supply
2018/04/04 全球购物
函数指针的定义是什么
2016/08/14 面试题
大学生自我鉴定范文
2013/12/28 职场文书
教师节活动总结
2014/08/29 职场文书
服务整改报告
2014/11/06 职场文书
2014年学校禁毒工作总结
2014/12/23 职场文书
运动会入场词
2015/07/18 职场文书
写好求职信的技巧解密
2019/05/14 职场文书
2019垃圾分类宣传口号汇总
2019/08/16 职场文书
golang 实现两个结构体复制字段
2021/04/28 Golang
新手入门Mysql--sql执行过程
2021/06/20 MySQL
Python面向对象编程之类的概念
2021/11/01 Python
CKAD认证中部署k8s并配置Calico插件
2022/03/31 Servers