探索 TypeScript 元组的用例

元组扩展了数组数据类型的功能。使用元组,我们可以轻松构造特殊类型的数组,其中元素相对于索引或位置是固定类型的。由于 TypeScript 的性质,这些元素类型在初始化时是已知的。使用元组,我们可以定义可以存储在数组中每个位置的数据类型。

在本教程中,我们将介绍 TypeScript 中命名元组的实际用例和应用程序。我们将了解这种数据类型的重要性以及为什么在某些情况下首选它。在一天结束时,我们将看到这种数据类型如何有助于改进 TypeScript 语言,根据改进的文档、可维护的代码和开发人员的生产力允许更严格的规则。

在我们开始之前,读者应该熟悉TypeScript和类型的基础知识。要了解有关此主题的更多信息,请查看 TypeScript 文档的这一部分。现在,让我们开始吧。

什么是元组?

元组就像具有额外功能的高级数组,可确保类型安全,特别是当我们需要考虑包含具有多个已知类型的固定数量的元素的列表时。

数组和元组之间的主要区别在于,当我们为元组赋值时,这些值必须以相同的顺序与元组声明中定义的类型匹配。另一方面,数组可以支持具有any类型或按位 OR ( | ) 运算符的多种类型,但元素的顺序或结构不起作用。

什么是命名元组?

命名元组提供了一种结构化方法,用于定义具有命名属性的数据。命名元组结合了数组和对象的优点,以清晰简洁的方式表示数据点。此外,命名元组增强了代码的可读性,并通过为属性分配名称来明确您的意图。

若要在 TypeScript 中定义命名元组,请使用方括号和类型注释的组合来指定属性的名称和类型。下面介绍如何在 TypeScript 中定义命名类型:

type MyNamedTuple = [name: string, age: number, isAdmin: boolean];

您已经定义了一个 MyNamedTuple 具有三个属性的命名元组:name的类型 stringage的类型number、 isAdmin的类型boolean 。类型定义中属性的顺序决定了实例化时元组中元素的顺序。

定义命名元组类型后,可以通过为属性赋值来声明和初始化该类型的变量,如下所示:

const person: MyNamedTuple = ['John Doe', 30, false];

您声明了该 MyNamedTuple 类型的变量 person 并为其分配了值。值的顺序对应于命名元组中定义的属性顺序。

使用元组的好处

在 TypeScript 程序中使用元组有很多好处。首先,元组是固定长度的序列,允许您定义元素的有序集合。当您需要表示一系列值(如坐标 ( x , y ) 或 RGB 颜色值 ( red , green , blue ) 时,元组很方便。固定长度有助于确保元组中具有正确数量的元素。

此外,您可以轻松地解构元组以提取单个元素,从而可以方便地使用一行代码将每个元素分配给单独的变量。解构元组可以提高可读性,尤其是在使用返回多个值的函数时。

此外,元组与数组有一些相似之处;您可以对它们执行类似数组的操作。您可以按索引访问单个元素,使用循环迭代它们并使用 map 、 filter 和 reduce 。但是,与数组不同,元组具有固定长度,这可确保元组的结构保持不变。下面是一个示例:

// Declare a tuple type
type MyTuple = [number, string, boolean];// Create a tuple
const myTuple: MyTuple = [10, "Hello", true];// Iterate over tuple elements with a loop
for (const element of myTuple) {console.log(element);
}// Use methods like map, filter, and reduce
const mappedTuple: MyTuple = myTuple.map((element) => element * 2);
console.log(mappedTuple); // Output: [20, "HelloHello", NaN]const filteredTuple: MyTuple = myTuple.filter((element) => typeof element === "string");
console.log(filteredTuple); // Output: [NaN, "Hello", NaN]const reducedValue: number = myTuple.reduce((acc, curr) => acc + (typeof curr === "number" ? curr : 0), 0);
console.log(reducedValue); // Output: 10

以下是在元组上运行常用数组操作的结果:

Example of TypeScript Tuples Running an Array

由于元组的优点和功能,元组优先于数组。元组强制实施固定长度,提供类型安全性,并允许异构数据。TypeScript 支持元组上的结构模式匹配,并启用简洁的函数签名。

解构赋值、只读属性和内存效率是额外的好处。类型推理和命名元组元素使元组对于结构化数据非常强大。

数组和元组数据类型简介

在我们开始探索 TypeScript 中元组的用例之前,让我们简要探讨一些可以使用数组的简单案例,以及元组如何在同一场景中完美地适应甚至更好。

在 TypeScript 中,我们可以声明一个特定数据类型的数组。例如,我们可以通过指定该元素的类型后跟方括号来声明一个数字数组:[]。让我们看看如何做到这一点:

let arr: number[];arr = [1, 2, 3];

正如我们从上面的例子中看到的,为了确保类型安全(这允许更容易地注释和记录我们的代码),我们需要使用数组,这允许像这样的情况,我们有特定数据类型的列表。事实上,这就是像TypeScript这样的类型语言的本质。

具有多种数据类型的数组

对于具有多种数据类型的数组,我们可以使用 any 类型或 | (按位 OR)运算符。但是,在这种情况下,数据的顺序不是一成不变的。让我们看下面的一个例子:

let arr: (string | number)[];
arr = ['Alex', 2020];
console.log(arr);

从上面的例子中,我们可以决定在字符串之前传递数字,它仍然有效。在这种情况下,实例化数组时传递数据的顺序无关紧要,因为我们具有指定类型的组合。这正是元组想要解决的问题。

使用元组,我们可以拥有一个多种数据类型的列表,其中我们传递数据类型的顺序必须符合声明元组时的顺序。本质上,元组的结构需要保持不变。让我们看一个例子来更好地理解这个概念:

let tup: [string, number];tup = ['Alex', 19087]

在上面的例子中,我们可以看到我们已经声明了一个具有两种基本数据类型的元组:string和 number 。请注意,当我们调用变量tup时,我们还必须按照声明的顺序传递元素类型。本质上,我们不能在索引为0处有一个数字和索引为1处有一个字符串,就像这样:

tup = [19087, 'Alex]

如果我们这样做了,我们将得到如下所示的错误:

TSError: ⨯ Unable to compile TypeScript:
index.ts:6:8 - error TS2322: Type 'number' is not assignable to type 'string'.6 tup = [19087, 'Alex']~~~~~
index.ts:6:15 - error TS2322: Type 'string' is not assignable to type 'number'.6 tup = [19087, 'Alex']

正如我们从上面前面的例子中看到的,我们正在声明一个数字数组并用值初始化它。只要我们只处理数字的元素类型,这就可以工作。为了考虑具有多种数据类型的数组,我们可以使用 any 类型或运算符,尽管在这种情况下,不能保证数据的顺序或 结构,这可能不是我们想要的。

但是,使用元组,我们可以确保数据类型和要传递的数据顺序的严格性。元组允许在具有固定数量的元素的元素类型周围指定已知类型边界。

TypeScript 元组用例

由于元组允许我们在数组中定义固定类型和顺序,因此在处理以顺序方式相互关联的数据(其中顺序很重要)时,它们是最好的选择。这样,我们可以轻松地以预定的方式访问元素,从而使我们期望的响应在行为上可预测。

下面,我们将基于 v4.2 版本在 TypeScript 中探索元组类型的更多用例,这些用例通常围绕在函数签名中提取和传播参数列表。

在 REST 参数中使用元组

REST 参数语法将参数收集到单个数组变量中,然后展开它们。在最近的 TypeScript 版本中,我们现在可以使用元组类型将 REST 参数扩展为离散参数。这意味着,当类型 tuple 用作REST参数时,它会平展到参数列表的其余部分。

简单来说,当 REST 参数是元组类型时,元组类型可以扩展为一系列参数列表。

请考虑以下示例:

declare function example(...args: [string, number]): void;

REST 参数将元组类型的元素扩展为离散参数。调用函数时, args 表示为 REST 参数的函数将展开为与下面的函数签名完全相同:

declare function example(args0: string, args1: number): void;

因此,REST 参数语法收集溢出到数组或元组中的参数。总之,元组类型迫使我们将适当的类型传递给相应的函数签名。TypeScript v4.2 增加了在前导或中间元素上展开的功能。这很方便,因为您可以使用 REST 参数在前导或中间参数上创建可变参数函数,如下所示:

type Matches = [string, boolean];const arsenal: Matches = ['Man City', true];
const city: Matches = ['Man United', true];
const hotspur: Matches = ['Liverpool', true];function processMatches(...matches: [...Matches[], string]): void {const lastMatch = matches.pop();console.log('Previous matches:');for (const match of matches) {console.log(match[0]);}console.log('Last match:', lastMatch);
}processMatches(arsenal, city, hotspur, 'Chelsea vs. Arsenal');

该 processMatches 函数接受具有展开语法的 ... 可变参数。该参数是 ,[...Matches[], string]这意味着它需要两个或多个类型的 Matches 元组,后跟一个字符串。

使用元组展开表达式

扩展语法将数组或对象的元素扩展为其元素。扩展运算符还可以扩展元组的元素。当函数调用包含元组类型的扩展表达式作为参数时,扩展表达式将扩展为与元组类型的元素对应的参数序列。让我们看下面的一个例子:

type Value = [number, number];const sample = (...value: Value) => {// do  something with value here
};// create a type
let sampleTuple: Value;sampleTuple = [20, 40];// Passing the values as literals:
sample(20, 40);// Passing indexes to the corresponding sampleTuple tuple
sample(sampleTuple[0], sampleTuple[1]);// Using the spread operator to pass the full sampleTuple tuple
sample(...sampleTuple);

注意,从上面的例子中我们可以看到,我们已经声明了一个元组类型,并将其作为参数传递给函数签名。

当函数被调用时,我们可以将参数作为文字或通过它们各自的索引传递。但是,使用 spread 运算符是将元组作为参数传递给函数调用的快速而干净的选项。由于扩散运算符的性质,参数被扩展为对应于元组类型元素的参数列表。

解构值

因为元组是底层的数组,我们可以像解构数组一样解构它们。重要的是要注意,解构变量获取相应元组元素的类型。让我们看一个例子:

let tuple: [number, string, boolean];tuple = [7, "hello", true];let [a, b, c] = tuple; // a: number, b: string, c: boolean

TypeScript 元组最佳实践

虽然元组有其优点,但在使用元组之前必须考虑权衡。元组不如数组和对象灵活,修改或扩展元组可能很麻烦。如果数据结构需要频繁修改或其他属性,您可能会发现数组或对象更合适。

创建有意义且可重用的元组类型的提示

创建定义明确且可重用的元组类型对于保持清晰度和减少代码重复至关重要。让我们讨论在 TypeScript 中定义和使用元组类型时要考虑的一些技巧。首先,请确保为元组中的元素分配有意义的名称,以提高可读性并帮助其他人了解每个值的用途。例如,请考虑 [x, y]`` [latitude, longitude] 。

此外,TypeScript 的类型推断系统可以根据元组类型的分配值自动推断元组类型。不应显式定义类型,而应依靠类型推断来减少冗余并提高代码可维护性。如果元组中的某些元素是可选的,请使用联合类型来指示可能存在的元素。灵活性可确保元组类型适应多种方案。

当元组很复杂或跨代码库的多个部分重用时,请考虑将它们抽象为接口或类型别名以实现可重用性,提高代码可读性,并允许将来更易于访问的修改和扩展。通过遵循这些提示,您可以创建有意义且可重用的元组类型,以增强 TypeScript 程序的清晰度和可维护性。

使用元组时要避免的错误

开发人员应注意一些常见的陷阱,以避免潜在的问题。在本节中,我们将介绍使用元组时要避免的一些常见错误。默认情况下,元组是不可变的。尝试修改元组的值将导致编译错误。避免直接更改元组元素;创建具有所需修改的新元组。

请记住,元组依赖于其元素的顺序来维护其结构。意外地对元素重新排序可能会引入难以发现的错误。为了防止这种情况,请使用清晰的描述性变量名称,并使用解构或命名元组元素按名称访问值,而不是仅依赖它们的顺序。

最后,过度使用元组会使代码更难理解和维护。如果数据结构需要频繁修改,请考虑使用对象或数组。避免这些错误将帮助您有效地利用 TypeScript 元组的强大功能并减少潜在的代码错误。

总结

TypeScript 元组就像具有固定数量的元素的数组。它们为我们提供了一个固定大小的容器,可以存储多种类型的值,其中顺序和结构非常重要。当我们确切地知道数组中允许多少种类型时,最好使用此数据类型。众所周知,在原始定义的长度之外分配索引将导致 TypeScript 编译器出错。

请注意,虽然可以通过元组元素的索引修改元组元素的值,但我们必须确保与声明元组变量时提供的类型匹配。这是因为一旦声明,我们就无法更改元组中元素的类型甚至大小。

通过我们在这篇文章中强调的功能,可以设计强类型的高阶函数,这些函数可以转换函数及其参数列表,并且本质上确保一个健壮的、有据可查的、可维护的代码库,这是我们使用 TypeScript 的核心。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/29446.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android, 笔记+课表的app实现

NoteSchedule: 笔记课表,不同于超表和课程格子等笔记类软件,笔记课表的核心是将课表和笔记进行深度绑定,点击每个课表,就进入到笔记view中,点击其中的item就可以进入到笔记详情; 该应用已上线,…

回归预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络多输入单输出回归预测

回归预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现POA-CNN…

Creo散热处理结构设计--阵列操作

问题描述: 在某一平面掏孔以散热,如何快速的绘制多孔并掏空处理 解决方式: 采用阵列操作。 1)绘制圆、拉伸处理 2)选择需要阵列的单元,选择阵列操作,在弹出的界面选择方向,按照…

【Winform学习笔记(七)】Winform无边框窗体拖动功能

Winform无边框窗体拖动功能 前言正文1、设置无边框模式2、无边框窗体拖动方法1、通过Panel控件实现窗体移动2、通过窗体事件实现窗体移动3、调用系统API实现窗体移动4、重写WndProc()实现窗体移动 前言 在本文中主要介绍 如何将窗体设置成无边框模式、以及实现无边框窗体拖动功…

[分享]STM32G070 串口 乱码 解决方法

硬件 NUCLEO-G070RB 工具 cubemx 解决方法 7bit 改为 8bit printf 配置方法 添加头文件 #include <stdio.h> 添加重定向代码 #ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endi…

并发多线程篇

线程的基础知识 面试题1&#xff1a;线程与进程的区别&#xff1f; 面试题2&#xff1a;并行和并发有什么区别&#xff1f; 面试题3&#xff1a;创建线程的方式有哪些&#xff1f; 面试题 4&#xff1a;runnable 和 callable 有什么区别&#xff1f; 面试题5&#xff1a;线程…

Git 快速入门

Git 快速入门 文章目录 Git 快速入门一、代码托管平台&#xff08;远程仓库&#xff09;二、安装Git三、Git的命令实践Git 的四个区域Git 管理代码的3个场景Git 工作区的理念Git 工作区的生命周期Git 版本回退Git 文件重命名Git查看版本提交日志Git StashGit分支Git标签 四、创…

Nginx与docker配置安装

目录&#xff1a; Nginx的安装配置&#xff1a; 1、安装依赖包&#xff1a; 2、下载Nginx安装包&#xff1a; 3、解压Nginx压缩包&#xff1a; 4、配置Nginx编译环境&#xff1a; 5、编译并安装Nginx&#xff1a; 6、安装完Nginx后&#xff0c;可以切换到Nginx的安装目录…

【TypeScript】TS接口interface类型(三)

【TypeScript】TS接口interface类型&#xff08;三&#xff09; 【TypeScript】TS接口interface类型&#xff08;三&#xff09;一、接口类型二、实践使用2.1 常规类型2.2 设置属性只读 readonly2.3 设置索引签名2.4 设置可选属性2.5 函数类型接口 一、接口类型 TypeScript中的…

【肌电图信号分析】通道肌电图并查找收缩周期的数量、振幅、最大值和持续时间(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

arcgis宗地或者地块四至权利人信息提取教程

ARCGIS怎样将图斑四邻的名称及方位加入其属性表 以前曾发表过一篇《 如何把相邻图斑的属性添加在某个字段中》的个人心得,有些会员提出了进一步的要求,不但要相邻图斑的名称,还要求有方位,下面讲一下自己的做法。 基本思路是:连接相邻图斑质心,根据连线的角度确定相邻图斑…

SQL-每日一题【1164. 指定日期的产品价格】

题目 产品数据表: Products 写一段 SQL来查找在 2019-08-16 时全部产品的价格&#xff0c;假设所有产品在修改前的价格都是 10 。 以 任意顺序 返回结果表。 查询结果格式如下例所示。 示例 1: 解题思路 1.题目要求我们查找在 2019-08-16 时全部产品的价格&#xff0c;假设所…

处理nacos、tomcat、nginx日志增长过快问题

1.nacos日志清理 修改nacos-logback.xml 将日志级别改为error级&#xff0c;减少info级日志产生量 将<maxHistory>调整为2以下&#xff0c;将 <totalSizeCap>调整为2GB左右 比如&#xff1a; [rootiZ0jlapur4hqjezy8waee0Z logs]# ll -h total 2.1G -rw-r--r-…

设计实现数据库表扩展的7种方式

设计实现数据库表扩展的7种方式 在软件开发过程中&#xff0c;数据库是一项关键技术&#xff0c;用于存储、管理和检索数据。数据库表设计是构建健壮数据库系统的核心环节之一。然而&#xff0c;随着业务需求的不断演变和扩展&#xff0c;数据库表中的字段扩展变得至关重要。 …

[OnWork.Tools]系列 06-屏幕水印

简介 屏幕水印功能主要是在开会分享屏幕的时候在屏幕上增加水印 水印使用 水印启用和颜色设置 水印文字和大小设置 水印间距,透明度,角度调整

centos安装python3的多个版本

标题 原本安装了python3.6&#xff0c;但是又有一个项目需要py3.7&#xff0c;所以需要让两个版本共存 操作 1、下载py3.7 wget https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz2、解压 tar -xzvf Python-3.7.3.tgz进入到文件夹 cd Python-3.7.33、安装 本人c…

day10 快速排序 方法重载 和 方法递推

方法重载 斐波拉契数列问题 使用重载思想解决 public static int method(int n){if (n 2 ){return 1 ;}return (n-1)*2method(n-1);}public static int f(int n){if (n 1){return 1;}if (n 2){return 2;}return f(n-1)f(n-2);} 快速排序 思维很简单&#xff0c;类似二…

Zookeeper 面试题

一、ZooKeeper 基础题 1.1、Zookeeper 的典型应用场景 Zookeeper 是一个典型的发布/订阅模式的分布式数据管理与协调框架&#xff0c;开发人员可以使用它来进行分布式数据的发布和订阅。 通过对 Zookeeper 中丰富的数据节点进行交叉使用&#xff0c;配合 Watcher 事件通知机…

【java】【maven】【高级】MAVEN聚合继承属性等

目录 1、模块开发与设计 2、聚合 2、继承 3、属性 4、版本管理 5、资源配置 6、多环境配置 7、多环境开发配置 8、跳过测试 9、私服 前言&#xff1a;maven的高级使用包含分模块开发与设计、聚合、继承、属性、版本管理、资源配置、多环境配置、多环境开发配置、跳过…

Spring Cloud 的版本和SpringBoot的版本

Spring Cloud 的版本选择 Spring Cloud 和SpringBoot的版本存在对应关系 Spring Cloud 的版本和SpringBoot的版本&#xff0c;存在对应关系。最新的SpringCloud版本&#xff08;发布文章时为2022.0.3&#xff09;&#xff0c;需要SpringBoot&#xff08;3.0.9&#xff09; 的…