浅谈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进行四舍五入方法汇总
Dec 16 Javascript
jQuery结合AJAX之在页面滚动时从服务器加载数据
Jun 30 Javascript
js图片翻书效果代码分享
Aug 20 Javascript
jQuery动态生成不规则表格(前后端)
Feb 21 Javascript
JavaScript 中Date对象的格式化代码方法汇总
Sep 06 Javascript
AngularJS 前台分页实现的示例代码
Jun 07 Javascript
浅析js中mvvm模式实现的原理
Oct 06 Javascript
React Hooks的深入理解与使用
Nov 12 Javascript
详解react-refetch的使用小例子
Feb 15 Javascript
js实现多个倒计时并行 js拼团倒计时
Feb 25 Javascript
Vue中的组件及路由使用实例代码详解
May 22 Javascript
微信小程序的开发范式BeautyWe.js入门详解
Jul 10 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
当海贼王变成JOJO风
2020/03/02 日漫
php array_intersect()函数使用代码
2009/01/14 PHP
php 数据库字段复用的基本原理与示例
2011/07/22 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十三)
2014/06/26 PHP
Laravel 5框架学习之表单
2015/04/08 PHP
深入解析PHP中foreach语句控制数组循环的用法
2015/11/30 PHP
YII2框架中日志的配置与使用方法实例分析
2020/03/18 PHP
JavaScript 在各个浏览器中执行的耐性
2009/04/06 Javascript
javascript权威指南 学习笔记之变量作用域分享
2011/09/28 Javascript
jquery.qtip提示信息插件用法简单实例
2016/06/17 Javascript
Vue.js每天必学之方法与事件处理器
2016/09/06 Javascript
Javascript json object 与string 相互转换的简单实现
2016/09/27 Javascript
Bootstrap3多级下拉菜单
2017/02/24 Javascript
Javascript封装id、class与元素选择器方法示例
2017/03/13 Javascript
canvas简单快速的实现知乎登录页背景效果
2017/05/08 Javascript
angularJs使用$watch和$filter过滤器制作搜索筛选实例
2017/06/01 Javascript
vue地址栏直接输入路由无效问题的解决
2018/11/15 Javascript
vue实现按需加载组件及异步组件功能
2019/05/27 Javascript
js布局实现单选按钮控件
2020/01/17 Javascript
JS 设计模式之:单例模式定义与实现方法浅析
2020/05/06 Javascript
通过实例了解Render Props回调地狱解决方案
2020/11/04 Javascript
Python工程师面试题 与Python基础语法相关
2016/01/14 Python
Python编程中对文件和存储器的读写示例
2016/01/25 Python
Python和JavaScript间代码转换的4个工具
2016/02/22 Python
通过Python使用saltstack生成服务器资产清单
2016/03/01 Python
Python2包含中文报错的解决方法
2018/07/09 Python
在pycharm中配置Anaconda以及pip源配置详解
2019/09/09 Python
Python中的__init__作用是什么
2020/06/09 Python
Python实现PS滤镜中的USM锐化效果
2020/12/04 Python
Reebok官方旗舰店:美国知名健身品牌锐步
2019/01/07 全球购物
临床医学系毕业生推荐信
2013/11/09 职场文书
小学生成长感言
2014/01/30 职场文书
数控个人求职信范文
2014/02/03 职场文书
城管大队整治方案
2014/05/06 职场文书
人事任命书格式
2014/06/05 职场文书
会计实训总结范文
2015/08/03 职场文书