ts中高阶类型的理解

news/2024/5/26 21:18:48/文章来源:https://blog.csdn.net/weixin_42776027/article/details/136656025

高阶类型是TypeScript中一种高级的类型操作,它允许你创建或修改现有类型的结构。这些类型通常作为其他类型的参数(即“泛型”)来定义新的类型。以下是一些常见的高阶类型示例:

  1. 映射类型(Mapped Types): 映射类型允许你基于一个现有类型创建一个新的类型,并对每个属性执行某种转换操作。例如,Partial<T> 类型会将 T 中的所有属性都变为可选:
       interface Person {name: string;age: number;}type PartialPerson = Partial<Person>;// 等同于 { name?: string; age?: number; }

  2. Pick<T, K> 和 Omit<T, K>
    • Pick<T, K> 从类型 T 中选择指定键 K 的属性构成新类型。
           interface Person {name: string;age: number;address: string;}type NameAndAge = Pick<Person, 'name' | 'age'>;// 等同于 { name: string; age: number; }

    • Omit<T, K> 则是从类型 T 中排除指定键 K 的属性。
           type WithoutAddress = Omit<Person, 'address'>;// 等同于 { name: string; age: number; }

  1. Record<K, V>: 创建一个对象类型,其中所有属性的键都是由 K 类型表示,值都是由 V 类型表示。
       type UserMap = Record<string, Person>; // 等同于 { [key: string]: Person; }

  2. ** keyof T 和 infer 关键字**:
     type KeysOfPerson = keyof Person; // "name" | "age" | "address"

    infer 在条件类型中用于推断类型。例如,在声明泛型时可以使用 infer 来从匹配的类型中提取子类型。

         type Unpacked<T> = T extends (infer U)[] ? U : T;// 此类型用于从数组类型中提取元素类型

 3.Conditional Types(条件类型): 允许根据某些条件表达式来确定类型

   type TypeName<T> = T extends string ? 'string' :T extends number ? 'number' :T extends boolean ? 'boolean' :'unknown';

通过这些高阶类型,开发者可以在TypeScript中实现更复杂、更灵活的类型定义和转换,进一步提升代码的类型安全性和可读性。

infer 是 TypeScript 中用于在条件类型(Conditional Types)中进行类型推断的关键字。它的主要作用是根据某种条件来提取或推断出未知类型的值。

下面是一个更具体的 infer 示例,解释如何从泛型参数中提取类型:

type MyPair<T> = [T, T];// 使用 infer 关键字定义一个 ExtractType 类型,它能从 MyPair 类型中提取出元素类型
type ExtractType<T> = T extends MyPair<infer U> ? U : never;// 测试用例
let pair1: MyPair<number> = [1, 2];
type NumberFromPair = ExtractType<typeof pair1>; // NumberFromPair 的类型被推断为 numberlet pair2: MyPair<string> = ['hello', 'world'];
type StringFromPair = ExtractType<typeof pair2>; // StringFromPair 的类型被推断为 string

在这个例子中:

  • 我们首先定义了一个泛型类型 MyPair,表示一个包含两个相同类型元素的数组。
  • 然后定义了 ExtractType 这个条件类型,使用 infer 来推断 MyPair 中的元素类型 U
  • 当 T 能够匹配 MyPair<infer U> 形式时,ExtractType<T> 的结果就是 U 类型;否则结果是 never 类型(表示不可能存在的类型)。

通过这种方式,我们可以从已知类型中“提取”或“推断”出内部嵌套的未知类型,这对于处理复杂的类型关系非常有用。

<infer U> ? U : never 这部分并不是固定的写法,但它是一种常见的 infer 关键字与条件类型结合的用法。

这里的结构遵循了 TypeScript 中条件类型的语法:

T extends U ? X : Y

其中:

  • T 是要检查的类型。
  • U 是用于比较的基础类型或类型构造器(在这个例子中是 MyPair<infer U>)。
  • X 是当 T 扩展自(或者说匹配)U 时的结果类型。
  • Y 是当 T 不扩展自(不匹配)U 时的结果类型。

在 <infer U> ? U : never 这个表达式中:

  • infer U 表示我们正在尝试从 T 中推断出一个未知类型 U
  • 当 T 可以成功地被解释为 MyPair<某种类型> 的形式时,infer U 将能够推断出那个“某种类型”,并将其作为结果类型返回,即 U
  • 如果 T 不能被解释为此形式,则结果类型是 never,表示不存在这样的类型。

所以这不是固定写法,但这种模式对于基于泛型或其他复杂类型进行类型推断的场景非常常见。根据具体需求,infer 和条件类型的具体使用可能会有所不同。

extends 在 TypeScript 中有多种含义和用法,主要体现在以下两个方面:

  1. 类继承: 在定义类(Class)时,可以使用 extends 关键字实现类之间的继承关系。子类会继承父类的属性和方法。
       class Animal {name: string;constructor(name: string) {this.name = name;}makeSound(): void {console.log('Making a sound');}}class Dog extends Animal {breed: string;constructor(name: string, breed: string) {super(name);this.breed = breed;}bark(): void {console.log('Woof woof!');}}

  2. 类型兼容性检查与条件类型: 在类型系统中,extends 用于判断一个类型是否兼容或扩展自另一个类型。这在泛型约束、接口继承以及条件类型中非常有用。

         

  • 泛型约束:限制泛型参数必须满足特定类型的要求。
         function identity<T extends string>(arg: T): T {return arg;}

    上述代码中的 `T extends string` 表示传入的泛型参数 `T` 必须是字符串类型或者其子类型。

  • 条件类型:根据条件判断返回不同的类型。
         type Unpacked<T> = T extends (infer U)[] ? U : T;

    此处的 `extends` 用于在条件类型表达式中进行类型检查,如果 `T` 扩展自数组类型,则推断并返回数组元素类型 `U`,否则返回 `T` 类型本身。

  • 总结来说,extends 是 TypeScript 中用来表示继承和类型兼容性的重要关键字,在面向对象编程和类型系统的复杂逻辑处理中起着关键作用。

Partial<T> 是 TypeScript 中的一个内置工具类型,它的作用就是将类型 T 中的所有属性都变为可选(optional)。

例如,假设我们有一个接口:

interface Person {name: string;age: number;address?: string; // 这个已经是可选属性了
}

如果我们想创建一个新的类型,其中所有的属性都是可选的,可以使用 Partial<T> 类型:

type OptionalPerson = Partial<Person>;// 等同于
// type OptionalPerson = {
//   name?: string;
//   age?: number;
//   address?: string;
// }

这样一来,当你在代码中使用 OptionalPerson 类型时,就不需要为任何属性提供值。而如果某个变量声明为 Person 类型,则必须为其所有非可选属性赋值。

Partial<T> 的核心功能就是将类型 T 中的所有属性(包括索引签名和方法)都变为可选。这意味着当你使用 Partial<T> 时,不需要为这些属性提供值就可以创建该类型的对象实例。

虽然从功能上看,Partial<T> 主要是为了实现属性转可选,但它的应用场景非常广泛,尤其是在处理可能不完整的数据结构、更新现有对象的部分属性或与外部接口交互(如API请求响应可能只返回部分数据)等方面,能有效提高代码的灵活性和健壮性。

keyof T 是 TypeScript 中用于获取类型 T 的所有公共属性键的类型操作符。它会返回一个联合类型,该联合类型包含 T 类型中所有可索引的公共属性名。

interface Person {name: string;age: number;address?: string; // 可选属性
}type PersonKeys = keyof Person; // 等同于 "name" | "age" | "address"

在这个例子中,PersonKeys 类型包含了 Person 接口的所有属性名称(包括可选属性)作为字符串字面量类型。

当你使用 keyof T 时,TypeScript 会生成一个表示对象所有可能键的类型,这对于编写更灵活且类型安全的代码非常有用,尤其是在处理映射、枚举对象属性或创建基于现有类型的接口和函数参数时。

当你在 TypeScript 中使用 keyof T 这个操作符时,TypeScript 编译器会分析类型 T 的结构,并生成一个新的类型,这个新类型包含了所有可以作为 T 类型对象的属性键(即键名)。

interface Person {name: string;age: number;address?: string; // 可选属性
}type KeysOfPerson = keyof Person;// 此时,KeysOfPerson 类型被推断为 "name" | "age" | "address"

在这个例子中,KeysOfPerson 类型代表了可以从 Person 接口中访问的所有合法属性名称。这意味着任何变量如果声明为 KeysOfPerson 类型,它可以是 "name""age" 或 "address"

这种类型的用途很多,比如在编写映射函数、创建动态属性访问或约束函数参数必须是给定类型的有效属性名等场景。

keyof T 主要用来获取类型 T 的所有合法键名,并生成一个可以表示这些键名联合类型的类型。这个类型主要用于检查和限制变量必须是给定对象类型的所有可能键名之一,确保在代码中使用的属性名是有效的、与类型 T 匹配的。它有助于提高代码的健壮性和可维护性,尤其是在处理动态属性访问或映射操作等场景时。

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

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

相关文章

豆瓣书影音存入Notion

使用Python将图书和影视数据存放入Notion中。 &#x1f5bc;️介绍 环境 Python 3.10 &#xff08;建议 3.11 及以上&#xff09;Pycharm / Vs Code / Vs Code Studio 项目结构 │ .env │ main.py - 主函数、执行程序 │ new_book.txt - 上一次更新书籍 │ new_video.…

贝叶斯优化CNN-BiLSTM回归预测(matlab代码)

贝叶斯优化CNN-BiLSTM回归预测matlab代码 贝叶斯优化方法则采用贝叶斯思想&#xff0c;通过不断探索各种参数组合的结果&#xff0c;根据已有信息计算期望值&#xff0c;并选择期望值最大的组合作为最佳策略&#xff0c;从而在尽可能少的实验次数下达到最优解。 数据为Excel股…

双系统合集——Ubuntu+Windows 10安装融合!

平时我们常见的电脑系统都是单一 一个Windows,当然,对于日常办公或娱乐足够了,但是对于发烧友来说,这种呆板了。万一某天系统崩溃了,只能泪两行。这时双系统就体现出他的优点了,一个系统崩溃了,还可以进入另一个系统使用,而且两个系统都是完全独立的,互不影响,开机时…

LeetCode.2864. 最大二进制奇数

题目 2864. 最大二进制奇数 分析 这道题目其实我们只需要保证最后一位是1&#xff0c;其余的1都放在最前面&#xff0c;这样得到的就是最大二进制奇数。 所以&#xff0c;我们先统计给定的字符串有多少个 1&#xff0c;多少个 0&#xff0c;把其中一个 1 放在最后一位&…

excel批量数据导入时用poi将数据转化成指定实体工具类

1.实现目标 excel进行批量数据导入时&#xff0c;将批量数据转化成指定的实体集合用于数据操作&#xff0c;实现思路&#xff1a;使用注解将属性与表格中的标题进行同名绑定来赋值。 2.代码实现 2.1 目录截图如下 2.2 代码实现 package poi.constants;/*** description: 用…

【智能算法】蜻蜓算法(DA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.代码实现4.参考文献 1.背景 2016年&#xff0c;Mirjalili受到蜻蜓静态和动态集群行为启发&#xff0c;提出了蜻蜓算法(Dragonfly algorithm, DA)。 2.算法原理 2.1算法思想 蜻蜓集群有两种行为目的&#xff1a;狩猎&#xf…

Java容器

容器 一、容器的概念二、Collection接口Collection接口的常用方法List和Set接口List接口List接口的实现类List接口特有的方法小结 Iterator接口Iterator接口的方法增强For循环&#xff08;For-each&#xff09;ListIterator Set接口Set接口中的实现类HashSetComparable接口sort…

OPPO后端二面,凉了!

这篇文章的问题来源于一个读者之前分享的 OPPO 后端凉经&#xff0c;我对比较典型的一些问题进行了分类并给出了详细的参考答案。希望能对正在参加面试的朋友们能够有点帮助&#xff01; Java String 为什么是不可变的? public final class String implements java.io.Seri…

从GPT入门,到R语言基础与作图、回归模型分析、混合效应模型、多元统计分析及结构方程模型、Meta分析、随机森林模型及贝叶斯回归分析综合应用等专题及实战案例

目录 专题一 GPT及大语言模型简介及使用入门 专题二 GPT与R语言基础与作图&#xff08;ggplot2&#xff09; 专题三 GPT与R语言回归模型&#xff08;lm&glm&#xff09; 专题四 GPT与混合效应模型&#xff08;lmm&glmm&#xff09; 专题五 GPT与多元统计分析&…

Linux--vim

一.什么是vim Vim&#xff08;Vi IMproved&#xff09;是一种文本编辑器&#xff0c;通常在Linux和其他类Unix操作系统中使用。它是Vi编辑器的增强版本&#xff0c;提供了更多的功能和定制选项。Vim具有强大的文本编辑和编程功能&#xff0c;支持语法高亮、代码折叠、宏录制、…

Nodejs 第五十五章(socket.io)

传统的 HTTP 是一种单向请求-响应协议&#xff0c;客户端发送请求后&#xff0c;服务器才会响应并返回相应的数据。在传统的 HTTP 中&#xff0c;客户端需要主动发送请求才能获取服务器上的资源&#xff0c;而且每次请求都需要重新建立连接&#xff0c;这种方式在实时通信和持续…

yolov8模型结构

yolov8模型结构 yolo发展历史yolov8简介yolov8模型结构 yolo发展历史 YOLOv1&#xff1a;2015年Joseph Redmon和 Ali Farhadi等 人&#xff08;华盛顿大学&#xff09; YOLOv2&#xff1a;2016年Joseph Redmon和Ali Farhadi等人&#xff08;华盛顿大学&#xff09; YOLOv3&…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:TextClock)

TextClock组件通过文本将当前系统时间显示在设备上。支持不同时区的时间显示&#xff0c;最高精度到秒级。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 TextClock(options?…

使用API有效率地管理Dynadot域名,使用API设置域名隐私保护

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

java代码将mysql表数据导入HBase表

java代码将mysql表数据导入HBase表 目录 一、项目目录介绍 二、主要接口方法与调用 三、全局配置文件 四、执行方式和输出介绍 五、项目依赖 一、项目目录介绍 主要包含四个接口:Com、RDB、HBase、RDBToHBase和其实现类xxxImpl。 两个配置文件:log4j日志配置文件log4j.pro…

Android App冷启动耗时优化

Android应用启动过程 Android应用启动过程&#xff0c;主要包含app::onCreate及执行前的Application阶段及Activity::onCreate执行之后的Activity阶段&#xff0c;以及两个阶段之间的间隙handleMessage阶段和最终页面渲染上屏完成前数据加载阶段四个区间组成。 具体来看&#x…

在 Android 上恢复已删除文件的 5 种简单方法

您可能会因为意外删除、未完成的 Android 更新、手机意外关机等原因而丢失 Android 上的重要数据。新技术的发展使许多手机功能或程序能够从内部恢复丢失的数据。 在 Android 上恢复已删除文件的 5 种简单方法 然而恢复成功率的不确定性也成为人们克服数据丢失困境的重要考虑因…

SQL语句在MySQL中的执行过程

有一条SQL语句&#xff0c;给到MySQL,是怎么被执行的 基本架构 连接器&#xff1a;进行身份认证&#xff0c;确定操作权限 查询缓存&#xff1a; 执行查询语句时&#xff0c;先查询缓存&#xff08;不太实用&#xff0c;MySQL 8.0 版本后删了&#xff09; 分析器&#xff1a…

运放的基础知识

运算放大器&#xff08;Operational Amplifier&#xff0c;简称运放&#xff09;是一种直流耦合、差模&#xff08;差动模式&#xff09;输入的高增益电压放大器&#xff0c;通常具有单端输出。它能产生一个相对于输入端电势差大数十万倍的输出电势&#xff08;对地而言&#x…

鸿蒙培训开发:就业市场的新热点~

金三银四在即&#xff0c;随着春节假期结束&#xff0c;各行各业纷纷复工复产&#xff0c;2024年的春季招聘市场也迎来了火爆的局面。最近发布的《2024年春招市场行情周报&#xff08;第一期&#xff09;》显示&#xff0c;尽管整体就业市场仍处于人才饱和状态&#xff0c;但华…