TypeScript中的 K、T 、V

封面

文章目录

  • 前言
  • 泛型类型
  • 链接关系
  • K、T、V 含义
  • 自动类型推断
  • 泛型的应用场景
    • 容器类和数据结构
    • 函数和方法
    • 接口和类
    • 类型约束和扩展
    • 常用的工具类型

前言

TypeScript 的泛型里经常会碰到一些字母,比如 KTV,是不是觉得很奇怪?

泛型类型

泛型参数
图中的 T 称为泛型类型参数,它是我们希望传递给函数的类型占位符

使用泛型类型参数可以使函数、类或接口在处理不同类型的数据时变得更加灵活通用。当我们定义泛型类型参数时,它会在函数、类或接口中作为一个占位符,表示可以接受任意类型的值。

链接关系

就像传递参数一样,我们获取用户指定的实际类型并将其链接参数类型返回值类型

链接到参数类型和返回值类型
链接到参数类型和返回值类型

K、T、V 含义

那么是什么T意思呢?图中的泛型类型参数T代表Type,实际上T可以替换为任何有效的名称。除了 之外T,常见的泛型变量还有 KVE 等。

  • K(Key):表示对象中key的类型
  • V(Value):表示对象中值的类型
  • E(Element):表示元素类型

K、T、V

K 和 V:

// 定义一个泛型接口,表示键值对
interface KeyValuePair<K, V> {key: K;value: V;
}// 使用 K 和 V 分别表示键和值的类型
let pair1: KeyValuePair<string, number> = { key: "age", value: 25 };
let pair2: KeyValuePair<number, boolean> = { key: 1, value: true };

E实现一个简单的队列(Queue)数据结构:

// 定义一个泛型队列类
class Queue<E> {private elements: E[] = [];// 将元素添加到队列末尾enqueue(element: E) {this.elements.push(element);}// 从队列头部移除并返回元素dequeue(): E | undefined {return this.elements.shift();}// 返回队列中的所有元素getAll(): E[] {return this.elements;}
}// 使用泛型队列存储数字
const numberQueue = new Queue<number>();
numberQueue.enqueue(1);
numberQueue.enqueue(2);
numberQueue.enqueue(3);
console.log(numberQueue.getAll()); // Output: [1, 2, 3]
console.log(numberQueue.dequeue()); // Output: 1// 使用泛型队列存储字符串
const stringQueue = new Queue<string>();
stringQueue.enqueue("apple");
stringQueue.enqueue("banana");
console.log(stringQueue.getAll()); // Output: ['apple', 'banana']
console.log(stringQueue.dequeue()); // Output: "apple"

当然,不必只定义一个类型参数,可以引入任意数量类型参数。这里我们引入了一个新的类型参数U,它扩展了我们定义的函数。

定义U
自动类型推断

自动类型推断

在调用identity函数时,我们可以显式指定泛型参数的实际类型
当然,你也可以不指定泛型参数的类型,让TypeScript自动帮我们完成类型推断

自动推断类型
自动推断类型

看完上面的动画,你是否已经了解泛型类型参数了?

泛型的应用场景

泛型在许多场景下都非常有用。下面是一些常见的泛型应用场景:

容器类和数据结构

泛型可以用于创建容器类数据结构,如数组、链表、栈和队列等。通过使用泛型,我们可以在这些数据结构中存储和操作不同类型的数据,而不需要为每种类型都编写单独的实现。


// 使用泛型创建一个通用的数组栈
class Stack<T> {private items: T[] = [];push(item: T) {this.items.push(item);}pop(): T | undefined {return this.items.pop();}
}// 使用字符串类型的栈
const stringStack = new Stack<string>();
stringStack.push("Hello");
stringStack.push("World");
console.log(stringStack.pop()); // Output: "World"// 使用数字类型的栈
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
console.log(numberStack.pop()); // Output: 2

函数和方法

泛型函数和方法可以适用于多种类型参数返回值。这使得我们可以编写更加通用和灵活的函数,而不需要为每种类型都编写重复的代码。


// 泛型函数用于反转数组
function reverseArray<T>(array: T[]): T[] {return array.reverse();
}const numbers = [1, 2, 3, 4, 5];
const reversedNumbers = reverseArray(numbers); // Output: [5, 4, 3, 2, 1]const strings = ["apple", "banana", "orange"];
const reversedStrings = reverseArray(strings); // Output: ["orange", "banana", "apple"]

接口和类

泛型还可以用于定义接口和类。通过使用泛型,我们可以创建可重用的接口和类,以适应不同类型的数据。这在编写通用的数据结构、算法和组件时非常有用。

使用泛型类型参数的接口:


// 泛型接口定义一个通用的 Pair 类型
interface Pair<T, U> {first: T;second: U;
}// 使用字符串和数字的 Pair
const pair1: Pair<string, number> = { first: "one", second: 1 };
const pair2: Pair<number, boolean> = { first: 42, second: true };

使用泛型类型参数的类:

class Box<T> {private value: T;constructor(value: T) {this.value = value;}getValue(): T {return this.value;}setValue(value: T) {this.value = value;}
}let box = new Box<string>("Hello");
console.log(box.getValue());  // output: "Hello"box.setValue("World");
console.log(box.getValue());  // output: "World"

类型约束和扩展

泛型还可以与类型约束和扩展一起使用,以限制泛型参数的类型范围或添加特定的行为。通过使用类型约束,我们可以确保泛型参数具有特定的属性或方法。这提供了更强的类型安全性和代码可读性。


// 使用类型约束确保泛型参数具有 length 属性
function getLength<T extends { length: number }>(obj: T): number {return obj.length;
}console.log(getLength("Hello")); // Output: 5
console.log(getLength([1, 2, 3])); // Output: 3
console.log(getLength({ length: 10, width: 5 })); // Output: 10// 使用类型约束确保泛型参数为数字类型
function sum<T extends number>(a: T, b: T): T {return a + b;
}console.log(sum(3, 4)); // Output: 7
console.log(sum(2, "test")); // Error: Argument of type '"test"' is not assignable to parameter of type 'number'.

常用的工具类型

为了方便开发者 TypeScript 内置了一些常用的工具类型:

Partial:将类型 T 中的所有属性变为可选属性。

interface User {name: string;age: number;email: string;
}function updateUser(user: Partial<User>, newName: string): User {return { ...user, name: newName } as User; 
}const user: User = {name: "Alice",age: 30,email: "alice@example.com",
};const updatedUser = updateUser({ age: 35 }, "Bob");
console.log(updatedUser);

Required:将类型 T 中的所有属性变为必选属性。

interface Props {name?: string;age?: number;
}function printInfo(info: Required<Props>) {console.log(info.name.toUpperCase(), info.age.toFixed(2));
}printInfo({ name: "John", age: 30 });

Readonly:将类型 T 中的所有属性变为只读属性。

interface Point {x: number;y: number;
}const point: Readonly<Point> = { x: 10, y: 20 };
// point.x = 5; // Error: Cannot assign to 'x' because it is a read-only property

Record<K, T>:创建一个具有指定键类型 K 和值类型 T 的对象类型

type Fruit = "apple" | "banana" | "orange";
const prices: Record<Fruit, number> = {apple: 1.5,banana: 2,orange: 1,
};

Pick<T, K>:从类型 T 中选择部分属性 K 组成新类型。

interface Person {name: string;age: number;address: string;
}type PersonInfo = Pick<Person, "name" | "age">;
// PersonInfo: { name: string; age: number; }

keyof: 获取给定类型的所有键(属性名)的联合类型。

interface Person {name: string;age: number;email: string;
}type PersonKeys = keyof Person;// PersonKeys 类型为 "name" | "age" | "email"

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

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

相关文章

ChatGPT提示词方法的原理

关于提示词&#xff0c;我之前的一些文章可以参考&#xff1a; 【AIGC】AI作图最全提示词prompt集合&#xff08;收藏级&#xff09;https://giszz.blog.csdn.net/article/details/134815245?ydrefereraHR0cHM6Ly9tcC5jc2RuLm5ldC9tcF9ibG9nL21hbmFnZS9hcnRpY2xlP3NwbT0xMDExL…

力扣● 583. 两个字符串的删除操作 ● 72. 编辑距离 ● 编辑距离总结篇

● 583. 两个字符串的删除操作 注意审题&#xff1a; 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。 删除最少的字符使两者相同&#xff0c;说明留下来的就是最大公共子序列。不要求…

13 秒插入 30 万条数据,这才是 Java 批量插入正确的姿势!

本文主要讲述通过MyBatis、JDBC等做大数据量数据插入的案例和结果。 30万条数据插入插入数据库验证 实体类、mapper和配置文件定义 User实体 mapper接口 mapper.xml文件 jdbc.properties sqlMapConfig.xml 不分批次直接梭哈 循环逐条插入 MyBatis实现插入30万条数据 J…

代码资源集合

代码资源 通信QPSKOQPSKMSK信道编码GMSK 雷达LFM及干扰技术LFM射频噪声干扰噪声调幅干扰噪声调频干扰噪声调相干扰固定移频干扰间歇采样干扰 SAR成像RD算法CS算法wk算法 SAR干扰技术射频噪声干扰调幅噪声干扰调频噪声干扰调相噪声干扰噪声卷积干扰乘积干扰移频干扰 DOA估计功率…

电学基础知识

目录 电流 前言 电流的产生 电流的单位安培&#xff08;A&#xff09; 电路和电池 开路和闭路 电灯泡原理 对电池容量的理解 毫安时 毫瓦时 直流电和交流电 AC交流电 DC直流电 直流电和交流电对比 电压 对电器的电压和电流的理解 电阻 电压电阻电子的关系 欧…

python--剑指offer--中等--07. 重建二叉树

输入某二叉树的前序遍历和中序遍历的结果&#xff0c;请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 例如&#xff0c;给出 前序遍历 preorder [3,9,20,15,7] 中序遍历 inorder [9,3,15,20,7] 返回如下的二叉树&#xff1a; 3/ 9 20 / 15 7 …

47.全排列II

// 定义一个Solution类&#xff0c;用于解决给定不重复整数数组的全排列问题 class Solution {// 初始化结果集&#xff0c;用于存放所有不重复的全排列组合List<List<Integer>> result new ArrayList<>();// 初始化路径变量&#xff0c;用于暂存当前递归生…

Vulnhub靶机:Kioptrix_Level1.3

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;192.168.56.101&#xff09; 靶机&#xff1a;Kioptrix_Level1.3&#xff08;192.168.56.109&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vul…

2024.3.18

1、试编程 封装一个动物的基类&#xff0c;类中有私有成员:姓名&#xff0c;颜色&#xff0c;指针成员年纪再封装一个狗这样类&#xff0c;共有继承于动物类&#xff0c;自己拓展的私有成员有:指针成员:腿的个数(整型intcount)&#xff0c;共有成员函数:会叫:void speak() 要求…

yocto系列之针对tarball编写recipes

回顾 针对借助yocto构建linux 镜像我们已经讲述了6部分&#xff0c; 简单回顾如下&#xff1a; Yocto: 第1部分 - yocto系列之yocto是个什么东东 https://mp.csdn.net/mp_blog/creation/editor/136742286 Yocto: 第2部分 - yocto系列之配置ubuntu主机 https://mp.csdn.net…

弗洛伊德-华沙算法求任意两点之间的最短路径算法

对于弗洛伊德-华沙算法首先是要假设研究的图中是不包含有负边的&#xff0c;对于所给的图中的任意亮点v1&#xff0c;vm&#xff0c;假设两点之间存在一条连通路径&#xff0c;对于该路径中去掉头和尾节点&#xff0c;也就是v1&#xff0c;vm&#xff0c;剩下的节点也就称之为这…

JNDI注入原理及利用IDEA漏洞复现

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

自定义全能搜索HTML源码

基础功能 可自定义通过筛选搜索&#xff0c;内容结果以嵌入方式展示&#xff0c;并不会直接跳转该地址显示&#xff0c;将以内嵌页面形式浏览&#xff0c;可自行添加其他地址搜索&#xff01;也可以做搜索引导页等等&#xff01; 界面布局&#xff1b; 源码为自适应端&#…

21-分支和循环语句_while语句(中)(初阶)

21-2 代码准备 getchar()&#xff1a;获取字符 int ch getchar(); //把获取的字符的ASCII码值放在ch中 int main() {int ch getchar();printf("%c\n", ch); //ch存的是该字符的ASCII码值&#xff0c;此处以字符形式打印ASCII码值对应的字符putchar(ch); } 运…

【2024第一期CANN训练营】3、AscendCL运行时管理

文章目录 【2024第一期CANN训练营】3、AscendCL运行时管理1. 初始化与去初始化2. 资源申请与释放2.1 申请流程2.2 释放流程2.3 运行模式&#xff08;可选&#xff09; 3. 数据传输3.1 接口调用流程3.2 主要数据传输场景1. Host内的数据传输2. 从Host到Device的数据传输3. 从Dev…

排序算法:快速排序(递归)

文章目录 一、创始人托尼霍尔的快速排序二、挖坑法三、前后指针法 所属专栏:C初阶 引言&#xff1a;这里所说的快速排序有三种&#xff0c;第一种是霍尔大佬自创的&#xff0c;还有一种叫做挖坑法&#xff0c;另外一种叫前后指针法 一、创始人托尼霍尔的快速排序 1.这里我们先…

拆解Spring boot:Springboot为什么如此丝滑而简单?源码剖析解读自动装配

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…

MySQL 篇- Java 连接 MySQL 数据库并实现数据交互

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 JDBC 概述 2.0 实现 Java 连接 MySQL 数据库并实现数据交互的完整过程 2.1 安装数据库驱动包 2.2 创建数据源对象 2.3 获取数据库连接对象 2.4 创建 SQL 语句 2.…

8.Python从入门到精通—Python 字符串,转义字符,字符串运算符

8.Python从入门到精通—Python 字符串,转义字符,字符串运算符 Python 字符串创建字符串访问字符串中的字符字符串切片字符串操作符字符串方法 Python 转义字符Python字符串运算符 Python 字符串 在 Python 中&#xff0c;字符串是一种基本数据类型&#xff0c;用于表示文本数据…

构建部署_Docker常用命令

构建部署_Docker常见命令 启动命令镜像命令容器命令 启动命令 启动docker&#xff1a;systemctl start docker 停止docker&#xff1a;systemctl stop docker 重启docker&#xff1a;systemctl restart docker 查看docker状态&#xff1a;systemctl status docker 开机启动&…