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

在本文中,我们将学习如何通过组合类型运算符和枚举来提取和声明常量类型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.hqwc.cn/news/8380.html

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

相关文章

MySQL的基本语法

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于MySQL的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.数据库&#xff08;建立&#xff0c;查…

备战秋招002(20230704)

文章目录 前言一、今天学习了什么&#xff1f;二、关于问题的答案1.线程池2.synchronized关键字3、volatile 总结 前言 提示&#xff1a;这里为每天自己的学习内容心情总结&#xff1b; Learn By Doing&#xff0c;Now or Never&#xff0c;Writing is organized thinking. …

【网络原理】TCP/IP协议五层模型

&#x1f94a;作者&#xff1a;一只爱打拳的程序猿&#xff0c;Java领域新星创作者&#xff0c;CSDN、阿里云社区优质创作者。 &#x1f93c;专栏收录于&#xff1a;计算机网络原理 本期讲解协议、OSI七层模型、TCP/IP五层模型、网络设备所在的分层、数据的封装和分佣。 目录 …

浏览器绘制图表的 N 种方法 | 可视化

前言 DORAVIS 可视化大屏编辑器&#xff0c;是植根于浏览器的可视化平台。我们不难发现&#xff0c;DORAVIS 的众多图表中&#xff0c;有多种实现方案。如&#xff0c;基于 ECharts 二次开发的 BI 图表&#xff0c;有基于 Mapbox/leaflet 等实现的地理图表&#xff0c;以及根据…

【Flutter 组件】005-基础组件:单选、开关和复选框

【Flutter 组件】005-基础组件&#xff1a;单选、开关和复选框 文章目录 【Flutter 组件】005-基础组件&#xff1a;单选、开关和复选框一、概述二、基本使用1、开关代码示例运行结果 2、复选框代码示例运行结果 3、多个选项单选代码示例运行结果 4、多个选项多选代码示例运行结…

易微联2.4G通断器添加到手机步骤

蓝牙款无WIFI&#xff0c;不用扫码&#xff0c;按住通断器上的按钮&#xff0c;会先闪一下&#xff0c;再闪两下。闪一下的时候连手机&#xff0c;闪两下清码。 手机上打开易微联app&#xff0c;依次点击加号/轻智能遥控器/单按键遥控器/添加完成。 返回打开刚才添加的开关&a…

图像处理--边缘检测算子

算子推导过程 1、知识引入&#xff1a; 在一维连续数集上有函数f(x),我们可以通过求导获得该函数在任一点的斜率&#xff0c;根据导数的定义有&#xff1a; 在二维连续数集上有函数f(x,y),我们也可以通过求导获得该函数在x和y分量的偏导数&#xff0c;根据定义有&#xff1a; …

升级Xcode14.3,项目无法运行解决

报错&#xff1a;link command failed with exit code 1(use -v to see invocaiton) 原因&#xff1a;新版本Xcode删除了特定目录下的一些文件 解决&#xff1a; post_install do |installer|installer.pods_project.targets.each do |target|target.build_configurations.e…

spring源码分析-ApplicationContext----扩展组件event listener

我们知道 spring中的ApplicationContext在beanFactory(提供基础bean处理)基础上增加了扩展组件&#xff0c;例如国际化&#xff0c;资源&#xff0c;发布事件和监听事件&#xff0c;今天主要针对发布和监听事件做一次源码分析&#xff0c;看到底发布和监听是如何实现的&#xf…

【性能工程】性能比较:REST vs gRPC vs 异步通信

微服务之间的通信方式对微服务架构内的各种软件质量因素有重大影响&#xff08;有关微服务网络内通信的关键作用的更多信息&#xff09;。沟通方式会影响软件的性能和效率等功能性需求&#xff0c;以及可变性、可扩展性和可维护性等非功能性需求。因此&#xff0c;有必要考虑不…

宝塔Panel搭建Python环境

服务器安装python环境 找到软件商店 应用搜索 输入&#xff1a;python 安装Python项目管理器2.4 开启首页显示 回到首页 找到python管理器并点击进入 安装对应的python版本 到这里 服务器就可以告一段落了 在本地开发服务端应用并上传服务器 将写好的python应用 导出依赖…

pytorch学习指南

安装anaconda&#xff1a; https://blog.csdn.net/fan18317517352/article/details/123035625 教程&#xff1a;bilibili up主&#xff1a;一只小土堆 构建pytorch空间 pytorch安装 查看cpu 安装命令pytorch&#xff1a;conda install pytorch torchvision torchaudio cpu…