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,一经查实,立即删除!

相关文章

【SysBench】sysbench-1.20 命令速查表

1、通用语法 The general command line syntax for sysbench is: sysbench [options]... [testname] [command] testname is an optional name of a built-in test (e.g. fileio, memory, cpu, etc.), or a name of one of the bundled Lua scripts (e.g. oltp_read_only), or…

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估计功率…

Linux:vim详解及使用

一、什么是vim vim的三种模式(其实有好多模式&#xff0c;目前掌握这3种即可),分别是命令模式&#xff08;command mode&#xff09;、插 入模式&#xff08;Insert mode&#xff09;和底行模式&#xff08;last line mode&#xff09;&#xff0c;各模式的功能区分如下&#…

电学基础知识

目录 电流 前言 电流的产生 电流的单位安培&#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 …

手把手带你入门学习TensorFlow

1. TensorFlow的来源及原理 TensorFlow是由Google Brain团队开发的开源深度学习框架&#xff0c;于2015年首次发布。它是一个功能强大、灵活且易于使用的工具&#xff0c;被广泛应用于机器学习和深度学习领域。TensorFlow的设计理念是通过构建计算图来表示复杂的数学运算和神经…

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…

Springboot自动校验@NotBlank@NotNull@NotEmpty

1、依赖问题&#xff1a; 查看搭建的SpringBoot项目中 NotEmpty 是否可以引用&#xff0c;查询资料发现从SpringBoot 2.3.0之后放弃了默认对javax.validation 的支持。 <dependency> <groupId>org.springframework.boot</groupId> …

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…

PHP修改默认上传文件缓存位置

php默认保存文件上传缓存的位置是 /tmp 版本小于php5.5 修改php.ini中**upload_tmp_dir ** upload_tmp_dir "/tmp/file" 版本大于和等于php5.5 修改php.ini中**sys_temp_dir ** sys_temp_dir "/tmp/file"谢谢大家观看&#xff0c;我们下次见

管理类联考–复试–英文面试–问题--规划介绍原因做法--汇总

文章目录 规划介绍原因做法 规划 一、提问方式&#xff1a;问题1&#xff1a;读研的规划&#xff1b;问题2&#xff1a;未来五年的规划&#xff1b;问题3&#xff1a;是否计划读博 常见问法1&#xff1a;Can you talk about your plans in the postgraduate period&#xff1f…

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

对于弗洛伊德-华沙算法首先是要假设研究的图中是不包含有负边的&#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;点赞➕评论➕收…

王道c语言-100元有几种换法

Description 一张面值100元的人民币换成10元、5元、2元和1元面值的票子。要求换正好40张&#xff0c;且每种票子至少一张。问&#xff1a;有几种换法&#xff1f; #include <stdio.h> int main() {int count 0;int i, j, t, k, ret 0;for (i 1; i < 37; i) {for …