探索 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 的核心。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

浪潮服务器硬盘指示灯显示黄色的服务器数据恢复案例

服务器数据恢复环境: 宁夏某市某单位的一台浪潮服务器,该服务器中有一组由6块SAS硬盘组建的RAID5阵列。 服务器上存放的是Oracle数据库文件,操作系统层面划分了1个卷。 服务器故障&初检: 服务器在运行过程中有两块磁盘的指示灯…

虹科方案 | 成都大运会进行时,保障大型活动无线电安全需要…

成都大运会 7月28日,备受关注的第31届世界大学生夏季运动会在成都正式开幕。据悉,这是全球首个5G加持的智慧大运会,也是众多成熟信息技术的综合“应用场”。使用基于5G三千兆、云网、8K超高清视频等技术,在比赛现场搭建多路8K摄像…

《UNIX 传奇:历史与回忆》读后感

《UNIX 传奇:历史与回忆》 是 bwk(Brian W. Kernighan)2019 年的新作,回忆了 UNIX 在大半个世纪的风雨历程,是一本引人入胜的书籍。通过对 UNIX 操作系统的历史和发展进行详细的叙述和回顾,让我对这个操作系…

vue table动态合并, 自定义合并,参照合并,组合合并

<template><div><el-table:data"tableData":span-method"objectSpanMethod"border:header-cell-style"{ textAlign: center }"><el-table-column prop"area" label"区域" align"center">…

java动态生成excel并且需要合并单元格

java动态生成excel并且需要合并单元格 先上图看一下预期效果 集成poi <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.0.0</version> </dependency> <dependency><…

为什么Mendix的OQL比SQL更方便,以及如何实现类似MySQL的workbench?

前言 在当今信息时代&#xff0c;数据的价值变得越来越重要。数据处理是任何软件系统都非常关注的核心功能。无论是电子商务网站、移动应用程序还是企业管理系统&#xff0c;这些系统都需要处理和管理大量的数据。例如&#xff0c;当用户在电子商务网站上搜索特定商品时&#…

无涯教程-Perl - formline函数

描述 格式功能和相关的运算符使用此功能。它根据PICTURE的内容将LIST格式化为输出累加器变量$^ A。写入完成后,该值将写出到文件句柄中。 语法 以下是此函数的简单语法- formline PICTURE, LIST返回值 该函数总是返回1。 Perl 中的 formline函数 - 无涯教程网无涯教程网提…

Octave Conv

Octave ConvOctave Convolution 代码详解_octconv代码_zghydx1924的博客-CSDN博客 def forward(self, x):X_h, X_l xif self.stride 2:X_h, X_l self.h2g_pool(X_h), self.h2g_pool(X_l)X_h2l self.h2g_pool(X_h)# X_h2l指的是对输入进行下采样&#xff0c;下采样的方法时卷…

【云原生】kubernetes在Pod中init容器的作用和使用

目录 Pod 中 init 容器 1 init 容器特点 2 使用 init 容器 Pod 中 init 容器 Init 容器是一种特殊容器&#xff0c;在Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。 1 init 容器特点 init 容器与普通的容器非常像&#xf…

【深度学习】Collage Diffusion,拼接扩散,论文,实战

论文&#xff1a;https://arxiv.org/abs/2303.00262 代码&#xff1a;https://github.com/VSAnimator/collage-diffusion 文章目录 AbstractIntroductionProblem Definition and Goals论文其他内容实战 Abstract 基于文本条件的扩散模型能够生成高质量、多样化的图像。然而&a…

【CSS】CSS 选择器

CSS 选择器 1.基础选择器 1.1 元素选择器 语法&#xff1a;标签名{...} 元素选择器会选中对应标签名的HTML元素&#xff0c;例如&#xff1a;p{...}&#xff0c;div{...}&#xff0c;span{...}等 1.2 类选择器 语法&#xff1a;.类名{...} 类选择器会选中class属性为指定…

【vue3-element-admin】ESLint+Prettier+Stylelint+EditorConfig 约束和统一前端代码

前言 本文介绍 vue3-element-admin 如何通过ESLint 检测 JS/TS 代码、Prettier 格式化代码、Stylelint 检测 CSS/SCSS 代码和配置 EditorConfig 来全方位约束和统一前端代码规范。 ESLint 代码检测 ESLint 可组装的JavaScript和JSX检查工具&#xff0c;目标是保证代码的一致…

Django入门 - Http协议前后端交互

Http协议前后端交互 在前后端交互当中&#xff0c;前端后端用的协议是http协议 先请求后响应&#xff0c;响应完之后连接就会断开我们可以认为它其实是一个短连接 或者 无连接。在它内部其实是基于TCP协议的&#xff0c;它也会有三次握手&#xff0c;但是这是内部的&#xff…

linux umask 详解

1. umask 定义 在 linux 系统中&#xff0c;umask 被定义在 /etc/profile 配置文件中&#xff0c;有一段 shell 脚本对 umask 是这么定义的。在 shell 会话输入命令&#xff1a; $ cat /etc/profile # 查看 /etc/profile 配置文件的内容 if [ $UID -gt 199 ] &&…

预测赢家(力扣)dfs + 备忘录 JAVA

给你一个整数数组 nums 。玩家 1 和玩家 2 基于这个数组设计了一个游戏。 玩家 1 和玩家 2 轮流进行自己的回合&#xff0c;玩家 1 先手。开始时&#xff0c;两个玩家的初始分值都是 0 。每一回合&#xff0c;玩家从数组的任意一端取一个数字&#xff08;即&#xff0c;nums[0]…

centos 7 系统上重启 mysql 时报错 Failed to restart mysqld.service: Unit not found.

在 centos 7 系统上&#xff0c;使用常规命令&#xff1a;systemctl restart mysql 或 service mysqld restart 重启 mysql 时都会报如下错误&#xff1a; Failed to start mysqld.service: Unit not found. 根据所报错误&#xff0c;在网上搜罗了一圈&#xff0c;未果&#x…

2023-08-05——JVM 栈

栈 stack 栈&#xff1a;数据结构 程序数据结构算法 栈&#xff1a;先进后出&#xff0c;后进先出 好比一个&#xff1a;桶 队列&#xff1a;先进先出&#xff08;FIFO &#xff1a;First Input First Out&#xff09; 好比一个&#xff1a;管道 栈&#xff1a;喝多了吐。队列…

STM32入门学习之独立看门狗(IWDG)

1.STM32的独立看门狗是一个具有独立时钟的片上外设。通常&#xff0c;为了防止程序卡死&#xff0c;可以设置看门狗定时复位。当看看门狗被使能之后&#xff0c;会按初始化时设置的计数值进行计数。当根据计数值计数的倒数时间为0时&#xff0c;便会自动复位程序&#xff0c;即…

STM32F103——GPIO八种工作模式

目录 1、GPIO 基本结构分析 2、GPIO 八种工作模式 2.1 输入浮空 2.2 输入上拉 2.3 输入下拉 2.4 模拟功能 2.5 开漏输出 2.6 开漏式复用功能 2.7 推挽输出 2.8 推挽式复用功能 3、GPIO 八种工作模式特点及应用 1、GPIO 基本结构分析 STM32F103的 GPIO 工作有八种…

iOS 实现图片高斯模糊效果

效果图 用到了 UIVisualEffectView 实现代码 - (UIVisualEffectView *)bgEffectView{if(!_bgEffectView){UIBlurEffect *blur [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];_bgEffectView [[UIVisualEffectView alloc] initWithEffect:blur];}return _bgEffect…