TypeScript 中对【泛型】的定义使用方式解读

news2025/1/9 19:04:42

目录

    • 泛型函数
    • 多个泛型参数
    • 泛型约束
    • 泛型别名
    • 泛型接口
    • 泛型类

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。使用泛型 可以复用类型并且让类型更加灵活

在这里插入图片描述
泛型实现类型参数化:

在定义这个函数时, 我不决定这些参数的类型
而是让调用者以参数的形式告知,我这里的函数参数应该是什么类型
把类型作为参数,放在尖括号中

泛型的基本使用

案例讲解:

当我们封装一个函数的时候,可能由于业务需求的不同,向函数内,传递的参数类型也不相同。而TS 的语法规范是,在函数定义的时候就需要为每个待接收的形参以及函数的返回值指定类型,如果在我们调用执行函数之前,就将类型给指定死了的话,这就大大降低了,函数的复用性了。


这时候,就可以使用 泛型,来实现这样的需求,将函数所需参数的类型,延后到,当我调用函数的时候,可以根据不同的业务需求再指定其参数类型。这样一来,将大大的提高函数的复用灵活性。

如下案例:

泛型函数

普通函数定义法

function createArray<T>(length: number, value: T): Array<T> {
    let result: T[] = [];
    for (let i = 0; i < length; i++) {
        result[i] = value;
    }
    return result;
}

createArray(3, 'x'); // ['x', 'x', 'x']

箭头函数定义法

let append = <T>(val: T, num: number): Array<T> => {
    const arr: T[] = []
    for (let index = 0; index < num; index++) {
        arr.push(val)
    }
    return arr;
}
console.log(append<string>("一段字符串", 9));
//['一段字符串', '一段字符串', '一段字符串', '一段字符串', '一段字符串', '一段字符串', '一段字符串', '一段字符串', '一段字符串']
console.log(append<number>(10086, 9));
//[10086, 10086, 10086, 10086, 10086, 10086, 10086, 10086, 10086]

我们在函数名后添加了 < T >,其中 T 用来指代任意输入的类型(泛型),后面的参数类型,以及函数返回值的类型,都可以 使用 T 泛型来定义站位。
console.log(append< string >("一段字符串", 9)); 在函数调用的时候再为其指定泛型所具体代表的类型,也可以不手动指定,而让类型推论自动推算出来(推荐手动指定,使其代码更加清晰明了)


多个泛型参数

定义泛型的时候,可以一次定义多个类型参数,同样的在调用的时候再为其指定参数类型,多泛型参数多用于元组类型的数据处理

普通函数写法:

function swap<T, U>(tuple: [T, U]): [U, T] {
    return [tuple[1], tuple[0]];
}

console.log(swap<number, string>([7, 'seven']));

箭头函数写法:

let swap = <T, U>(tuple: [T, U]): [U, T] => {
    return [tuple[1], tuple[0]];
}

console.log(swap<string, number>(["字符串", 100]));

泛型约束

由于泛型,表示数据的类型的待定的,由于事先不知道它是哪种类型,所以不能够随意操作一个待定数据类型身上的方法属性,如果传进来的数据类型没有这个属性方法,则就会引起报错。

如下案例:

function loggingIdentity<T>(arg: T): T {
    console.log(arg.length);
    return arg;
}

// 报错:  index.ts(2,19): error TS2339: Property 'length' does not exist on type 'T'.

上例中,泛型 T 不一定包含属性 length,所以编译的时候报错了。

这时候,我们就可以通过接口对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束:

interface Lengthwise {
    length: number;
}

function loggingIdentity<T extends Lengthwise>(arg: T): T {
    console.log(arg.length);
    return arg;
}

上例中我们使用了 extends 约束了泛型 T 必须符合接口 Lengthwise 的形状,也就是必须包含 length 属性。

此时如果调用 loggingIdentity 函数的时候,传入的 arg 数据类型身上 不包含 length 属性,那么在编译阶段就会报错了,这样一来就大大降低了,会发生在函数体内部的错误了。

补充

多个类型的参数之间也可以互相约束

function copyFields<T extends U, U>(target: T, source: U): T {
    for (let id in source) {
        target[id] = (<T>source)[id];
    }
    return target;
}

let x = { a: 1, b: 2, c: 3, d: 4 };

copyFields(x, { b: 10, d: 20 });

上例中,我们使用了两个类型参数,其中要求 T 继承 U,也相当于,U 约束了 T ,这样就保证了 U 上不会出现 T 中不存在的字段。


泛型别名

在类型别名 type 的后面使用<T>即可声明一个泛型参数,接口里的其他成员都能使用该参数的类型

type len = {
    length: number
}

let fun = <T extends len>(x: T): number => {
    return x.length
}
console.log(fun<string>("486789413"));//9

泛型接口

前面提到过,interface 是我们在使用 TypeScript 的时候,用来定义接口的关键字。

如:

interface Person {
  name: string;
  age: number;
}
const dome: Person = {
  name: "sunny",
  age: 18,
};

上面示例的代码中用声明接口限制了一个对象,我们也可以通过泛型对我们的接口进行改造

在这里插入图片描述

这时候我们通过定义泛型的方式,定义 T ,U 两个占位符,使得我们的接口具备了泛型,更加灵活。但是我们发现 泛型接口和泛型函数不一样,像上图中这样使用,有一个地方报错了,提示我们需要传入类型参数,而不能依赖自动的类型推断,来确实对象属性的类型,其实这也是可以理解,因为我们对一个对象的限制,主要就是限制对象的属性类型,如果我们不确定类型,那我们传入的一切类型都是有效的了。就起不到类型的限制,而前面我们使用泛型函数,虽然没有显示声明类型,但是我们达到了对函数入参和出参进行了统一。

interface Person<T, U> {
    name: T;
    age: U;
}
const dome: Person<string, number> = {
    name: "sunny",
    age: 18,
};

所以定义泛型接口的时候,正确的写法应该是 对其传入了两个确定的类型。T,U的类型也因此确定了。

泛型接口来约束函数:

interface Person<T> {
    (value: T): Array<T>
}

const printFun: Person<string> = <T>(value: T): Array<T> => {
    let arr: T[] = [];
    arr.push(value)
    return arr;
};
console.log(printFun("233")); //['233']

泛型类

与泛型接口类似,泛型也可以用于类的类型定义中:

class information<T, U>{
    name: T
    age: U
    constructor(name: T, age: U) {
        this.name = name;
        this.age = age
    }
}
let c =  new information<string, number>("张三", 48)

泛型参数的默认类型

在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用。

class information<T = string, U = number>{
    name: T
    age: U
    constructor(name: T, age: U) {
        this.name = name;
        this.age = age
    }
}
let c = new information("李四", 25)

总结:

泛型德优势是什么?

增加类型的复用性和灵活性。

泛型实现的基本方法是什么?

  • 找到不确定类型的部分,为其定义泛型参数
  • 传入参数时,为泛型指定具体的类型

泛型约束的作用是什么?

既可以,保留泛型的灵活性,又限制了一定的规范


🚵‍♂️ 博主座右铭:向阳而生,我还在路上!
——————————————————————————————
🚴博主想说:将持续性为社区输出自己的资源,同时也见证自己的进步!
——————————————————————————————
🤼‍♂️ 如果都看到这了,博主希望留下你的足迹!【📂收藏!👍点赞!✍️评论!】
——————————————————————————————

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

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

相关文章

Pycharm安装 leetcode 插件

目录 本节演示Pycharm安装 leetcode 插件做算法题 打开设置&#xff1a; 点击插件&#xff1a; 搜索leetcode并安装&#xff1a; 点这里的 leetcode&#xff1a; 初次使用点这里&#xff1a; 这里输入账号和密码&#xff1a; 点击确定后还是点登录&#xff1a; 登…

【MySQL】SQL入门(一)

&#x1f697;MySQL学习起始站~ &#x1f6a9;本文已收录至专栏&#xff1a;数据库学习之旅 ❤️每章节附章节思维导图&#xff0c;文末附全文思维导图&#xff0c;感谢各位点赞收藏支出~ 一.引入 (1) SQL分类 SQL语句&#xff0c;根据其功能&#xff0c;主要分为四类&#x…

巧妙使用 CSS 渐变来实现波浪动画

目录 一、波浪的原理 二、曲面的绘制 三、波浪动画 四、文字波浪动画 五、总结一下 参考资料 之前看到coco[1]的这样一篇文章&#xff1a;纯 CSS 实现波浪效果&#xff01;[2]&#xff0c;非常巧妙&#xff0c;通过改变border-radius和不断旋转实现的波浪效果&#xff0c…

网络安全—全知识点解析(课程学习笔记)

概括来说&#xff0c;网络安全课程的主要内容包括&#xff1a; 安全基本知识 应用加密学 协议层安全 Windows安全&#xff08;攻击与防御&#xff09; Unix/Linux安全&#xff08;攻击与防御&#xff09; 防火墙技术 入侵监测系统 审计和日志分析 下面分别对每部分知识介绍相应…

Stable Diffusion - ControlNet 插件中扩展局部重绘 InpaintOnly + LaMa 算法与应用

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131643131 LaMa: https://github.com/advimman/lama Paper: Resolution-robust Large Mask Inpainting with Fourier Convolutions LaMa: Large…

哇~~真的是你呀!今天是在LINUX上简单部署LAMP平台。

目录 一、概述 二、PHP安装配置 三、安装 四、启动 五、书写测试页面 六、客户端访问 七、安装论坛 一、概述 LAMP组成&#xff1a; &#xff08;1&#xff09; Linux 其他组件的平台 &#xff08;2&#xff09;Apache提供web服务 &#xff08;3&#xff09;MySQL|Ma…

004-Triple协议底层原理分析

目录 底层分析Http 2.0 底层分析 Http 2.0 为了解决Http 1.0 和 1.1 头信息无法压缩有很多比如空格、换行等无用字符请求和相应不能并行处理&#xff1a;一个Socket连接如果接受到Request 就必须要等到服务返回Response了才能继续发送另一个Request 就更新了Http的协议到2.…

SQL语法与数据库快速入门(1)

目录 数据库简介数据库分类常用数据库简介使用场景MySql 的安装与配置数据库客户端工具MySql 介绍SQL 简介DDL 数据库操作-创建DDL 数据库操作-查看DDL 数据库操作-修改DDL 数据库操作-删除DDL 数据库表操作简介DDL 数据库表操作-创建DDL 数据库表操作-查看DDL 数据库表操作-修…

国内值得去的外企之Google攻略

外企在国内非常的乖&#xff0c;基本上都是正常上下班&#xff0c;更有甚者&#xff0c;上班不到点不进门&#xff0c;下班一到点就跑路&#xff0c;中途还能去楼下咖啡店喝咖啡。 年假多、生活工作平衡、待遇还不错&#xff0c;下班以后同事之间几乎再无联系&#xff0c;如果…

解决matplotlib子图重叠问题

代码修改前&#xff1a; import matplotlib.pyplot as plt import seaborn as snsdef on_resize(event):print(当前画布大小为&#xff1a;{}x{}.format(event.width, event.height))if __name__ __main__:x list(range(1, 6))y1 [i ** 2 for i in x]y2 [i ** 3 for i in …

C++之std::set有序容器用法(一百六十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Redis安装与配置指南:适用于Windows、Mac和Linux系统的详细教程

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

Django实现接口自动化平台(九)环境envs序列化器及视图【持续更新中】

相关文章&#xff1a; Django实现接口自动化平台&#xff08;八&#xff09;测试报告reports序列化器及视图【持续更新中】_做测试的喵酱的博客-CSDN博客 本章是项目的一个分解&#xff0c;查看本章内容时&#xff0c;要结合整体项目代码来看&#xff1a; python django vue …

3D全景虚拟旅游在旅游行业中具备哪些应用价值?

在网络强国战略指引下&#xff0c;我们的网络基础设施建设步伐正在加快&#xff0c;与此同时&#xff0c;虚拟技术也在不断的更新迭代&#xff0c;虚拟旅游也逐渐崭露头角&#xff0c;将真实世界中的景点、文化以及历史场景等数字化&#xff0c;让游客身临其境地感受这些景点和…

【C语言】深入解密C语言组包与解包的用法、应用以及const的详细解说

目录 一、sprintf 用于组包 应用1&#xff1a;按照规定格式组包 应用2&#xff1a;将数值类型转换成字符串类型 二、sscanf 用于解包 应用1&#xff1a;%d提取数值‘0’~‘9’ 应用2&#xff1a;%s提取字符串&#xff08;遇到\0 空格 回车结束提取) 三、sscanf高级应用 1、…

Unity3D+Hololens2+MRTK开发

最近项目要用Hololens2开发&#xff0c;公司新买了几套Hololens2设备&#xff0c;边学习边研究下吧。开始也是网上搜教程&#xff0c;但是问题还挺多的&#xff0c;大部分人的设置都不太对&#xff0c;有的是版本问题&#xff0c;走了好多弯路。现在就从零开始学习下Hololens2吧…

网络编程——RPC与HTTP基本介绍、历史追溯、主流应用场景、对比分析、为什么还需要使用RPC

一、HTTP与RPC基本介绍 HTTP协议&#xff08;Hyper Text Transfer Protocol&#xff09;超文本传输协议&#xff1a; 一个用于在网络上交换信息的标准协议&#xff0c;它定义了客户端(例如浏览器)和服务器之间的通信方式。如平时上网在浏览器上敲个网址url就能访问网页&#x…

Vue--》打造个性化医疗服务的医院预约系统(一)

今天开始使用 vue3 ts 搭建一个医院预约系统的前台页面&#xff0c;因为文章会将项目的每一个地方代码的书写都会讲解到&#xff0c;所以本项目会分成好几篇文章进行讲解&#xff0c;我会在最后一篇文章中会将项目代码开源到我的GithHub上&#xff0c;大家可以自行去进行下载运…

智慧农场丨2023年数字经济发展助力生态农场规划

智慧农场丨2023年数字经济发展助力生态农场规划 导读&#xff1a;生态农场是保护环境和发展农业的新模式&#xff0c;它遵循生态平衡规律&#xff0c;在持续利用的原则下开发利用农业自然资源&#xff0c;进行多层次、立体、循环利用的农业生产&#xff0c;使能量和物质流动在生…

【大数据之Hive】二十三、HQL语法优化之数据倾斜

1 数据倾斜概述 数据倾斜指参与计算的数据分布不均&#xff0c;即某个key或者某些key的数据量远超其他key&#xff0c;导致在shuffle阶段&#xff0c;大量相同key的数据被发往同一个Reduce&#xff0c;导致该Reduce所需的时间远超其他Reduce&#xff0c;成为整个任务的瓶颈。  …