在 TypeScript 中有效地使用 keyof 和 typeof 来表示类型

news2024/11/25 18:59:28

在本文中,我们将学习如何通过组合类型运算符和枚举来提取和声明常量类型typeof,以使您的代码库得到优化。keyof

先决条件

为了获得更好的编码体验,您应该在 IDE 中安装 TypeScript,例如VSCode。它将为您提供许多基本功能,例如错误突出显示、IntelliSense、linting 等...您还应该安装一些扩展,例如JavaScript 和 TypeScript Nightly、ESLint等。

什么是typeof

在 TypeScript 中,我们可以用来typeof提取变量或属性的类型,如下例所示:

``` const Name = { firstName: 'Maya', lastName: 'Shavin' };

let myName: typeof Name; ```

在上面的代码中,我们使用myName从变量 中提取的类型来声明变量Name,这将是一个具有两个属性 -firstName和 的对象lastName。当鼠标悬停myName在 IDE 中时,TypeScript 将向您显示myName结论的类型Name,如以下屏幕截图所示:

显示名称类型的屏幕截图,其中名字和姓氏作为其属性

这里注意typeof,如果要提取类型的变量是一个 Object,那么接收到的类型将是一个完整的类型结构,并且每个属性都有其类型(例如 type of 将有myName两个字段 - firstNameof typestringlastNameof kind string)。

另一个有价值的场景typeof是将其与ReturnType从函数中提取返回数据的类型结合起来。为此,我们执行以下操作:

  1. 使用以下方法获取声明函数的函数类型typeof
  2. 使用ReturnType<T>withT是步骤 1 中提取的类型来获取 from 的返回值类型T

下面的例子演示了如何提取返回类型decoupleName()

``` function decoupleName (name: string) { const [firstName, ...remaining] = name.split(" ");

return {
    firstName,
    lastName: remaining.reduce((text, word) => text ? `${text} ${word}` : word, '')
}

}

type NameObj = ReturnType ```

TypeScript 将自动引用正确的类型NameObj,如下面的屏幕截图所示:

显示 NameObj 类型(其属性为名字和姓氏)的屏幕截图

此外,我们可以typeof在 TypeScript 中用作条件块内的类型保护,就像在 JavaScript 中一样,尽管在这种情况下,它主要适用于stringobjectfunction等基本类型...

现在我们了解了typeof它的用法。接下来我们就来探讨一下keyof

理解keyof

虽然typeof生成由变量表示的类型,但keyof采用对象类型并生成作为该变量键的自由联合的类型,如下所示:

``` interface User { firstName: string; lastName: string; };

type UserKeys = keyof User ```

以上等同于以下声明:

type UserKeys = "firstName" | "lastName"

但是,与 不同的是typeof,您不能keyof直接在变量上使用。对于以下代码,TypeScript 将引发错误:

``` const Name = { firstName: 'Maya', lastName: 'Shavin' };

type NameKeys = keyof Name; //error ```

要从对象变量(例如常量值的对象映射)中提取类型,我们需要结合keyoftypeof,我们接下来将学习这一点。

从对象的键(或属性)中提取typeOf

以下面的ImageVariables为例,它充当修改图像时使用的变量的映射:

export const ImageVariables = { width: 'w', height: 'h', aspectRatio: 'ar', rotate: 'a', opacity: 'o', } as const;

请注意,这里我们需要const对象末尾的 来将其指示为只读。否则,TypeScript 将不允许我们从中提取类型,因为存在随时修改对象内部属性的风险。

ImageVariables包含从其键到根据Cloudinary 机制转换图像时使用的匹配变量符号的映射。要根据 的属性(或键)生成类型ImageVariables,我们执行以下操作:

  1. ImageVariables获取代表使用的类型typeof

type ImageVariablesType = typeof ImageVariables

  1. 根据类型的键提取新类型ImageVariablesType,使用keyof

type ImageFields = keyof ImageVariablesType

或者,我们可以将上述两个步骤合二为一,如下所示:

type ImageFields = keyof typeof ImageVariables

就是这样。我们现在有了ImageFieldstype,其中包含 的接受字段ImageVariables,如下面的屏幕截图所示:

显示 ImageFields 类型的屏幕截图,其中 ImageVariables 的所有键作为其可接受的值

我们现在可以使用这个生成的类型,如下所示:

``` const transformImage = (field: ImageFields) => { const variable = ImageVariables[field]

//do something with it

} ```

通过基于 的属性声明类型ImageVariables,任何使用 的流程transformImage都是安全的,并且我们可以确保field传递的内容始终需要存在于 中ImageVariables。否则,TypeScript 将检测任何错误并向用户发出警报。

将 ImageFields 中不存在的值传递给函数 TransformImage 时,TypeScript 显示错误的屏幕截图

此外,Intellisense 将告知用户可接受的值,限制传递错误值的可能性。

显示接受值传递给transformImage的提示下拉列表的屏幕截图

顺便说一句,类型检查的行为与hasOwnProperty()运行时检查类似,尽管它只发生在编译时。

听起来很简单。如果我们想将键的值提取到ImageVariables新类型中怎么办?我们接下来看一下。

从对象的键(或属性)的值中提取typeof

如果我们想从 的键值生成一个类型ImageVariables,我们可以执行以下操作:

type VariableValues = typeof ImageVariables[ImageFields]

由于我们已经声明ImageVariablesType为 of 类型ImageVariables,因此我们可以将上面的内容重写为:

type VariableValues = ImageVariablesType[ImageFields]

通过上面的代码,我们现在有了一个新类型,VariableValues它接受以下值:

显示从 ImageVariables 键值生成的类型的屏幕截图

从命名常量对象的值和键生成类型在许多情况下都是有利的,例如当您必须使用各种数据映射并且标准键或值在它们之间进行映射时。在对象映射上使用keyoftypeof可以帮助创建相关映射和类型之间的连接,从而避免潜在的错误。

或者,我们可以结合枚举 和typeof来实现相同的目标。

使用枚举

枚举是声明命名常量类型的一种方便且有组织的方式。它允许我们创建一组不同的常量值,并且每个枚举字段都是基于数字或基于字符串的。我们可以重写我们ImageVariables的如下:

enum EImageVariables { width = 'w', height = 'h', aspectRatio = 'ar', rotate = 'a', opacity = 'o', }

使用枚举的优点之一是我们可以使用枚举的名称作为接受值声明的类型。因此,代替以下代码:

``` type VariableValues = typeof ImageVariables[ImageFields]

function transform(value: VariableValues) { //perform something } ```

EImageVariables我们可以使用如下方式重写:

function transform(value: EImageVariables) { //perform something }

对于更少的代码,类型检查执行相同的操作。尽管如此,为了从声明的 enum 的键(或属性)获取类型,我们仍然需要像常规常量对象一样EImageVariables使用组合:keyof typeof

type ImageFields = keyof typeof EImageVariables

就是这样。上面的代码产生的结果与我们使用ImageVariables.

现在让我们回顾一下如何从常量对象的键和值获取类型:

``` export const ImageVariables = { width: 'w', height: 'h', aspectRatio: 'ar', rotate: 'a', opacity: 'o', } as const;

type ImageVariablesType = typeof ImageVariables; type ImageFields = keyof ImageVariablesType; type VariableValues = ImageVariablesType[ImageFields]; ```

与使用枚举相比:

``` enum EImageVariables { width = 'w', height = 'h', aspectRatio = 'ar', rotate = 'a', opacity = 'o', }

type EImageVariablesType = typeof EImageVariables; type EImageFields = keyof EImageVariablesType; //No need for getting the type of values ```

与常量对象一样,我们可以直接使用枚举键的值,例如EImageVariables.width在我们的代码中。在运行时,枚举作为 JavaScript 对象存在于编译后的代码中,并且表现得像 JavaScript 对象。

一般来说,枚举是可以的。在 TypeScript 中,由于其实现方式效率低下(希望这个问题已得到修复或会很短),许多人认为它对性能有影响。

那么我们应该使用它们吗?这取决于。这个选择由你。

概括

在使用 TypeScript 时,我们经常忽略类型运算符,例如typeof或 ,keyof因为它们太初级了。然而,它们在构建类型系统中发挥着重要作用。当正确结合其他 TypeScript 语法时,它们可以帮助您的应用程序开发高级和复杂的类型。让我们尝试一下它们,看看它们能为您带来什么。

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

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

相关文章

Linux——进程通信之共享内存

目录 一. 回顾上文 二.共享内存 1.定义 2.特点&#xff1a; 3.实现步骤&#xff1a; 如下为成功链接共享内存使用权的完整步骤&#xff1a; 4.函数介绍 4.1shmget函数 4.1.2参数介绍 4.2ftok函数&#xff1a; 4.2.1参数介绍 关于ftok(); shmget();函数的代码实验…

基于当量因子法、InVEST、SolVES模型等多技术融合在生态系统服务功能社会价值评估中的应用

查看原文>>>基于当量因子法、InVEST、SolVES模型等多技术融合在生态系统服务功能社会价值评估中的应用及论文写作、拓展分析 本文将讲述用于评估生态系统服务价值的当量因子法、InVEST模型、SolVES模型及其原理&#xff0c;您将学会三种模型的原理与运行方法&#xf…

基于Docker的JMeter分布式压测

目录 前言&#xff1a; Docker Docker在JMeter分布式测试中的作用 Dockerfile用于JMeter基础&#xff1a; Dockerfile for JMeter Server / Slave: 总结 前言&#xff1a; 基于Docker的JMeter分布式压测是一种将JMeter测试分布在多个容器中进行的方法&#xff0c;可以提高…

《计算机系统2》学习笔记

目录 计算机系统漫游 Amdahl定理 信息的表示和处理 信息存储 进制转化 小端法 大端法 布尔代数 位级运算 逻辑运算 移位运算 整数表示 无符号数编码 补码编码 有符号数和无符号数之间的转换 扩展数的位表示 截断数字 整数运算 无符号加法 无符号数求反 有…

信号链噪声分析5

目录 概要 整体架构流程 技术名词解释 技术细节 小结 概要 提示&#xff1a;这里可以添加技术概要 残余相位噪声测量法消除了外部噪声源&#xff08;例如电源或输入时钟&#xff09;的影响&#xff0c;而绝对相位 噪声测量法包含了这些来源的噪声。残余相位噪声装置可以隔离并…

Upload靶场通关笔记

文章目录 一、Pass-011.抓包上传2.获取上传路径3.工具验证 二、Pass-02三、Pass-031.使用httpd.conf自定义后缀2.提取上传文件名3.工具测试4.注意点四、Pass-041.上传.htaccess2.上传图片3.工具测试 五、Pass-05六、Pass-061.空格.号绕过2.工具测试 七、Pass-07八、Pass-081.特…

联想黄莹:6G将是全智能应用下连接虚拟与现实世界的“超级通道”

6月28日&#xff0c;以“时不我待”为主题的MWC上海世界移动通信大会正式开幕。在当天下午举办的“6G愿景及关键推动力”大会论坛上&#xff0c;联想集团副总裁、联想研究院5G实验室负责人黄莹博士发表了“共铸辉煌&#xff1a;对6G技术和应用的思考与展望”主题演讲。他认为&a…

STM32F407 GPIO口输出配置配置步骤

STM32F407ZGT6 是意法半导体&#xff08;STMicroelectronics&#xff09;公司推出的一款高性能ARM Cortex-M4核心的32位微控制器&#xff08;MCU&#xff09;。它是 STM32F4 系列的一员&#xff0c;具备强大的处理能力和丰富的外设功能&#xff0c;适用于各种应用领域。 【1】…

3.6.6.异步SIGIO : fcntl(F_GETFL、F_SETFL、O_ASYNC、F_SETOWN) 3.6.7.存储映射IO

3.6.6.异步IO &#xff1a;SIGIO 3.6.6.1、何为异步IO (1)几乎可以认为&#xff1a;异步IO就是操作系统用软件实现的一套中断响应系统。 (2)异步IO的工作方法是&#xff1a;我们当前进程注册一个异步IO事件&#xff08;使用signal注册一个信号SIGIO的处理函数&#xff09;&…

【Django学习】(十)模型序列化器_关联字段序列化

这篇文章是针对模型类序列化器以及如何关联字段序列化 进行深入讲解的&#xff1b; class ProjectModelSerializer(serializers.ModelSerializer):email serializers.EmailField(write_onlyTrue)interfaces InterfaceModelSerializer(label所属接口的信息, help_text所属接口…

git常见操作汇总

存档&#xff0c;方便本人查询~ 除了add、commit、push、pull外有些操作也是需要掌握的~在复习之前先准备一下需要的项目&#xff1a; mkdir git-demo1 cd git-demo1 git init基础操作 # 在工作区新增一个README.md文件&#xff0c;并写入 # Hello World# 查看哪些原件做了修…

Java安全——安全管理器

Java安全 安全管理器 Java安全管理器是一个Java安全模型中的一个组件&#xff0c;主要的作用是提高Java应用程序的安全性。Java应用程序中的每个线程都会对安全管理器进行检查&#xff0c;在执行代码之前&#xff0c;会先经过安全管理器的核验&#xff0c;安全管理器根据代码来…

Flink SQL之Temporal Joins

1.Temporal Joins&#xff08;时态JOIN&#xff09; 时态表是一个随时间演变的表&#xff0c;在Flink中也称为动态表。 时态表中的行与一个或多个时态周期相关联&#xff0c;并且所有Flink表都是时态的&#xff08;动态的&#xff09;。时态表包含一个或多个版本化的表快照&a…

Oracle数据库中的包的介绍及示例

Oracle的包是一种封装存储过程&#xff0c;函数&#xff0c;变量和游标等代码对象的方法。包可以视为一组相关的程序单元&#xff0c;它们共享相同的命名空间和存储空间。包可以被看做是一个数据库程序库&#xff0c;它包含一个或多个程序单元&#xff0c;这些单元可以被视为一…

图片加载失败捕获上报及处理

图片加载失败捕获上报及处理 前端页面中加载最多的静态资源之一就是图片了&#xff0c;当出现图片加载失败时&#xff0c;非常影响用户体验。这时候我们就需要对图片是否成功加载进行判断&#xff0c;并对图片加载失败进行处理。 图片加载监听 单个捕获 HTML中的img标签可以…

vue 组件简单实例及传参交互

前言:vue 可以比较灵活的使用 html的片段&#xff0c;并将html的片段进行数据隔离&#xff0c;参数也可以互相传递&#xff0c;组件与组件之间也可以进行数据的交互 合理的使用组件可以避免重复代码或者很方便的调用第三方组件库 vue组件 简单实例组件传参实际应用父子组件交互…

SpringBoot2+Vue2实战(四)进行组件内容拆分及路由实现

一、拆分 新建包&#xff1a; Aside和Header都是组件 User为视图 Aside.vue&#xff1a; <template><el-menu :default-openeds"[1, 3]" style"min-height: 100%; overflow-x: hidden"background-color"rgb(48, 65, 86)"text-color…

I2C总线协议详解

I2C总线物理拓扑结构 I2C总线物理拓扑图 I2C 总线在物理连接上非常简单&#xff0c;分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制&#xff0c;来 产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时&#…

linux下使用pyqt5的QMediaPlayer制作简易播放器(存在进度条、前进、后退、暂停、打开、播放等操作)

目录 1. 问题2. 解决3. 效果 1. 问题 关于pyqt5的qmediaplayer模块制作简易播放器&#xff0c;网上很多博客都是win下的&#xff0c;放在linux系统会出问题&#xff1b;另外&#xff0c;部分博客缺少文件&#xff0c;无法直接使用。 参考博客《基于pyqt5的QMediaPlayer实现视…

android studio git使用

pull代码 我们从远程仓库拉取代码时&#xff0c;一般有下面的两个选项 当使用Android Studio拉取代码时&#xff0c;有两种常见的选项&#xff1a;合并&#xff08;merge&#xff09;传入的更改到当前分支和变基&#xff08;rebase&#xff09;。 合并&#xff08;Merge&…