TypeScript体操(一):从基础到进阶

目录

    • 前言
    • Utility Types 是什么?
    • 常用 Utility Types
    • 前置知识
      • `typeof`
      • `keyof`
      • `typeof` 和 `keyof` 的区别
      • `never` 关键字
      • `extends` 关键字结合条件判断
      • `infer` 类型推断(模式匹配)
      • 判断是与非
      • 判断两个类型是否相等或兼容
    • 循环
    • 递归嵌套
    • 字符串数组
    • 协变(Covariance)
    • 逆变(Contravariance)

前言

TypeScript 体操(TypeScript Gymnastics)是指在 TypeScript 中进行各种类型操作和转换的技巧。这些技巧可以帮助我们更好地利用 TypeScript 的类型系统,提高代码的安全性和可维护性。Utility Types 是 TypeScript 2.8 版本引入的,它们提供了一种方式来转换和操作现有的类型。


在这里插入图片描述

正文开始如果觉得文章对您有帮助,请帮我三连+订阅,谢谢💖💖💖


Utility Types 是什么?

Utility Types 是一种特殊的类型,它们不是具体的值类型,而是可以对现有类型进行操作的类型。这些操作包括但不限于:选择属性、排除属性、从属性中提取类型等。

常用 Utility Types

TypeScript 提供了许多内置的 Utility Types,以下是一些常用的 Utility Types:

  • Partial<T>:将类型 T 的所有属性设置为可选。
  • Readonly<T>:使类型 T 的所有属性变为只读。
  • Pick<T, K>:从类型 T 中选取部分属性,创建一个新的类型。
  • Omit<T, K>:从类型 T 中排除部分属性,创建一个新的类型。
  • Record<K, T>:创建一个类型,其键为 K 类型,值为 T 类型的字典。
  • Exclude<T, U>:从类型 T 中排除类型 U 的所有属性。
  • Extract<T, U>:从类型 T 中提取出类型 U 的所有属性。

前置知识

typeof

typeof 是一个 JavaScript 操作符,用于获取一个变量或属性的类型。在 TypeScript 中,typeof 也用于获取一个位置的类型,但它通常与类型守卫一起使用来区分不同的情况。

  • 基本用法

    let myVar: string = "Hello, World!";
    console.log(typeof myVar); // "string"let obj = {name: "张三",age: 20,
    };
    type ObjType = typeof obj; // { name: string; age: number; }
    
  • 与类型守卫一起使用

    function printId(something: any) {switch (typeof something) {case "string":console.log(`String: ${something}`);break;case "number":console.log(`Number: ${something}`);break;default:console.log(`Unknown`);}
    }
    

keyof

keyof 是 TypeScript 中的一个关键字,用于从类型中提取所有公共属性的键,这些键可以是字符串字面量或者数字或符号,取决于属性的类型。

  • 基本用法

    type Point = {x: number;y: number;
    };type PointKeys = keyof Point; // "x" | "y"
    
  • 用于索引访问操作

    let point: Point = { x: 1, y: 2 };
    let key: keyof Point = "x"; // "x" | "y"
    console.log(point[key]); // 1
    

typeofkeyof 的区别

  1. 用途

    • typeof 通常用于在运行时获取变量的类型。
    • keyof 用于在编译时从类型中提取键。
  2. 类型

    • typeof 的结果是一个类型,如 "string""number""boolean" 等。
    • keyof 的结果是联合类型,表示一个类型的所有键。

never 关键字

  1. 两个不相交的基本类型进行相交操作为 never
  2. never 和任何类型相交操作,返回 never
  3. 两个相同的基本类型进行联合操作为其本身
type Str1 = "a" & "c"; // Str1 = never
type Str2 = "a" & never; // Str2 = never
type Str3 = "a" | "a"; // Str3 = "a"

extends 关键字结合条件判断

这个关键字有两个功能:1. 继承属性,2. 条件判断。

条件类型,如同代码中的 if ... else 或三目运算

type A = string;
type B = number;
type Example = A extends B ? true : false; // false

infer 类型推断(模式匹配)

模式匹配是 TypeScript 最有用的特性之一,许多复杂类型操作都基于它。

type A = [1, 2, 3];
type ExampleA = A extends [infer First, ...infer Rest] ? First : never; // 1
type B = "123";
type ExampleB = B extends `${infer FirstChar}${infer Rest}` ? FirstChar : never; // '1'type InferArray<T> = T extends (infer C)[] ? C : never;
const item: InferArray<number[]> = 1; // number

判断是与非

// 与,即 C1,C2 同为真
type And<C1 extends boolean, C2 extends boolean> = C1 extends true? (C2 extends true ? true : false): false;// 或,即 C1,C2 有一个为真
type Or<C1 extends boolean, C2 extends boolean> = C1 extends true? true: C2 extends true? true: false;// 非,即反转 C 的真假状态
type Not<C extends boolean> = C extends true ? false : true;

判断两个类型是否相等或兼容

type CheckLeftIsExtendsRight<T, R> = T extends R ? true : false;
type Example1 = { a: 1; b: 2 } extends { a: 1 } ? true : false; // true
type Example2 = 1 | 2 extends 1 ? true : false; // false

循环

extends 分布式条件类型,当泛型参数 T 为联合类型时,条件类型即为分布式条件类型,会将 T 中的每一项分别分发给 extends 进行比对。
in 映射类型,固定写法,in 操作符会分发 T 成为新对象类型的键。

  1. extendsin 都可以遍历键。
  2. extendsnever 能过滤一些不想要的值。
type Example1<T> = T extends number ? T : never;
type Result1 = Example1<"1" | "2" | 3 | 4>; // 3 | 4// 映射类型,固定写法,in 操作符会分发 T 成为新对象类型的键
interface Person {name: string;age: number;sex: boolean;
}
type Example2<T> = {[Key in keyof T]: T[Key];
};
type Result = Example2<Person>; //  { name: string; age: number; sex: boolean;}type BaseType = string | number;
type Example3<T> = {[Key in keyof T as T[Key] extends BaseType ? Key : never]: T[Key];
};
type Result2 = Example3<Person>; //  { name: string; age: number; }

递归嵌套

type Example<C extends boolean = true, Tuple extends unknown[] = [1]> = C extends true? Example<false, [...Tuple, 1]>: Tuple;type Result = Example; // [1, 1]

字符串数组

type NumberLike = number | `${number}`;
let a: NumberLike = '6';

协变(Covariance)

协变是指如果类型 A 是类型 B 的子类型,那么 T<A> 也是 T<B> 的子类型。换句话说,类型可以在其子类型之间进行转换。

例子:常规赋值

class Animal {name = 'null';
}class Dog extends Animal {breed = '金毛';
}let animals: Animal = new Animal();
let dogs: Dog = new Dog();
dogs.name = '旺财';animals = dogs; // 协变,子类型可以赋值给父类型
// dogs = animals; // error : animals 中缺少 breed 字段console.log(animals.name); // 旺财

在这个例子中,DogAnimal 的子类型,我们可以将 Dog 赋值给 Animal,并打印 name

逆变(Contravariance)

逆变是指如果类型 A 是类型 B 的子类型,那么 T<B>T<A> 的子类型。换句话说,父类型参数可以赋值给子类型参数。

例子:函数参数

class Animal {name = 'null';
}class Dogextends Animal {breed = '金毛';
}let treatAnimal = (animal: Animal) => {console.log(`Treating animal: ${animal.name}`);
};let treatDog = (dog: Dog) => {console.log(`Treating dog: ${dog.breed}`);
};treatDog = treatAnimal; // 逆变,父类型参数可以赋值给子类型参数
// treatAnimal = treatDog; // Error: 不能将子类型参数赋值给父类型参数const myDog = new Dog();
myDog.name = "BB";
myDog.breed = "边牧";treatDog(myDog);

在这个例子中,treatDog 接受 Dog 类型参数,而 treatAnimal 接受 Animal 类型参数。由于 DogAnimal 的子类型,所以 treatDog 可以赋值给 treatAnimal


这篇文章介绍了 TypeScript 中一些常见的类型操作技巧。通过掌握这些技巧,你可以更好地利用 TypeScript 的类型系统,提高代码的安全性和可维护性。希望这篇文章对你有所帮助!

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

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

相关文章

NMEA2000在船舶控制系统中航空插头插座组件特性

NMEA2000在船舶控制系统中的应用概述 NMEA2000协议是船舶电子设备之间通信的国际标准&#xff0c;广泛应用于船舶导航、监控和自动化系统。它基于CAN&#xff08;Controller Area Network&#xff09;总线技术&#xff0c;以确保在恶劣环境下的可靠性和效率。NMEA2000协议定义了…

英语语法第八课副词

文章目录 1、副词分类1.1 时间副词&#xff0c;表示时间或频率1.2 地点副词&#xff0c;表示地点或位置1.3 方式副词&#xff0c;表示行为方式1.4 程度副词&#xff0c;表示动作程度1.5 疑问副词&#xff0c;引导特殊疑问句1.6 强调副词&#xff0c;强调形容词或动词1.7 连接副…

隐语隐私计算实训营「联邦学习」第 5 课:基于隐私保护的机器学习算法介绍

【隐私计算实训营】是蚂蚁集团隐语开源社区出品的线上课程&#xff0c;自实训营上线以来&#xff0c;获得行业内外广泛关注&#xff0c;吸引上千余名开发者报名参与。本次暑期夏令营课程中&#xff0c;除了最新上线的「联邦学习系列」&#xff0c;还包含了「隐私保护数据分析」…

Java项目实战springboot校园失物招领系统

✌网站介绍&#xff1a;✌10年项目辅导经验、专注于计算机技术领域学生项目实战辅导。 ✌服务范围&#xff1a;Java(SpringBoo/SSM)、Python、PHP、Nodejs、爬虫、数据可视化、小程序、安卓app、大数据等设计与开发。 ✌服务内容&#xff1a;免费功能设计、免费提供开题答辩P…

3D建模软件--犀牛Rhino for Mac

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功 三、运行测试安装完成&#xff01;&#xff01;&#xff01; 效果 一、下载软件 下载软件…

初学Mybatis之配置解析

MyBatis 中文网配置教程 mybatis-config.xml 环境配置&#xff08;environments&#xff09; 尽管可以配置多个环境&#xff0c;但每个 SqlSessionFactory 实例只能选择一种环境 可以有多个 enviroment&#xff0c;但是 enviroments default&#xff08;默认&#xff09;只…

动态规划题目:单词拆分/三角形最小路径和 - leetcode

动态规划思想 / 步骤 &#xff1a; 先将 当前要求 总结成一个 精炼的 小问题 &#xff0c; 然后 将 求解题目 转换为 求解N个 小问题 &#xff0c; 每个小问题的 求解过程相同 &#xff0c;但是 过程涉及 的 数据 是不同的 &#xff0c; 例如第三个 小问…

c++网络编程实战——开发基于ftp协议的文件传输模块(二) 配置ftp服务与手动执行ftp命令

配置FTP服务 一.前言 博主的环境是阿里云服务器&#xff0c;操作系统版本为 ubuntu20.04,一下所有操作都基于以上环境下进行的操作&#xff0c;同时为了简化操作我将开放同一个云服务器的不同端口&#xff0c;让它同时充当服务端和客户端&#xff0c;大家如果想测试效果更好且…

WPF串口通讯程序

目录 一 设计原型 二 后台源码 一 设计原型 二 后台源码 using HardwareCommunications; using System.IO.Ports; using System.Windows;namespace PortTest {/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainW…

软件缺陷(Bug)、禅道

目录 软件缺陷的判定标准 软件缺陷的核心内容 构成缺陷的基本要素 缺陷报告 缺陷管理 缺陷的跟踪流程 项目管理工具--禅道 软件在使用过程中存在的任何问题&#xff08;如&#xff1a;错误、异常等&#xff09;&#xff0c;都叫软件的缺陷&#xff0c;简称bug。 软件缺…

如何选择海洋船舶用总线NMEA 2000连接器

NMEA 2000连接器概述 NMEA 2000连接器是现代船舶通信系统中不可或缺的部分&#xff0c;主要用于连接船上各种电子设备&#xff0c;实现数据传输和设备控制。这些连接器遵循NMEA 2000协议标准&#xff0c;支持高速数据传输&#xff0c;并具有良好的防水、耐腐蚀性能&#xff0c…

神经网络之循环神经网络

目录 一、循环神经网络概述&#xff1a;1.传统神经网络与循环神经网络的区别&#xff1a;2.循环神经网络定义&#xff1a; 图片来自&#xff1a;深度学习———循环神经网络 一、循环神经网络概述&#xff1a; 1.传统神经网络与循环神经网络的区别&#xff1a; MLP、卷积神经…

【PostgreSQL教程】PostgreSQL 选择数据库

博主介绍:✌全网粉丝20W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…

多目标遗传算法(NSGAⅢ)的原理和matlab实现

参考文献&#xff1a; [1] Deb K , Jain H .An Evolutionary Many-Objective Optimization Algorithm Using Reference-Point-Based Nondominated Sorting Approach, Part I: Solving Problems With Box Constraints[J].IEEE Transactions on Evolutionary Computation, 2014,…

【Simple PIR】单服务器开源最快匿踪查询算法解析

7月17日&#xff0c;我们在《隐私计算匿踪查询技术深入浅出》中介绍了关于隐私计算中匿踪查询的定义和常见算法&#xff0c;并引出了前沿算法Simple PIR的介绍&#xff0c;本次将对Simple PIR进行正式的算法原理介绍。 1. Simple PIR快览 1.1 性能介绍 Simple PIR是Alexandra…

docker 打包orbbec

docker pull humble容器 sudo docker run -it osrf/ros:humble-desktop docker 启动容器 sudo docker run -u root --device/dev/bus/usb:/dev/bus/usb -it -v /home/wl:/share --name wl4 osrf/ros:humble-desktop /bin/bash新开一个终端 查看本地存在的容器&#xff1a;…

高速ADC模拟输入接口设计

目录 基本输入接口考虑 输入阻抗 输入驱动 带宽和通带平坦度 噪声 失真 变压器耦合前端 有源耦合前端网络 基本输入接口考虑 采用高输入频率、高速模数转换器(ADC)的系统设计是一 项具挑战性的任务。ADC输入接口设计有6个主要条件&#xff1a; 输入阻抗、输入驱动、带宽…

开源模型应用落地-FastAPI-助力模型交互-进阶篇-中间件(四)

一、前言 FastAPI 的高级用法可以为开发人员带来许多好处。它能帮助实现更复杂的路由逻辑和参数处理&#xff0c;使应用程序能够处理各种不同的请求场景&#xff0c;提高应用程序的灵活性和可扩展性。 在数据验证和转换方面&#xff0c;高级用法提供了更精细和准确的控制&#…

IPython魔法命令的深入应用

目录 IPython魔法命令的深入应用 一、魔法命令基础 1. 魔法命令的分类 2. 基本使用 二、高级应用技巧 1. 数据交互与处理 2. 交互式编程与调试 三、魔法命令的进阶操作 1. 自定义魔法命令 2. 利用魔法命令优化工作流程 四、总结与展望 IPython魔法命令的深入应用 IP…

vulnhub——Ai-Web1靶机渗透

Ai-Web1靶机渗透 靶机下载&#xff1a; 官网地址&#xff1a;https://www.vulnhub.com/entry/ai-web-1,353/ 攻击机&#xff1a;kali2024 一、信息收集 发下目标主机的IP为&#xff1a;192.168.201.141 用nmap工具扫描一下对方主机和服务 发现他打开了80端口 发现搜不到于是…