TypeScript 关于对【泛型】的定义使用解读

目录

    • 概念导读
    • 泛型函数
    • 多个泛型参数
    • 泛型约束
    • 泛型别名
    • 泛型接口
    • 泛型类
    • 总结:


概念导读

泛型(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: Tage: Uconstructor(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: Tage: Uconstructor(name: T, age: U) {this.name = name;this.age = age}
}
let c = new information("李四", 25)

总结:

泛型德优势是什么?

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

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

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

泛型约束的作用是什么?

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


注明:在正式开发中,泛型的使用场景非常多…


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

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

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

相关文章

安全第二次

一&#xff0c;iframe <iframe>标签用于在网页里面嵌入其他网页。 1&#xff0c;sandbox属性 如果嵌入的网页是其他网站的页面&#xff0c;因不了解对方会执行什么操作&#xff0c;因此就存在安全风险。为了限制<iframe>的风险&#xff0c;HTML 提供了sandb…

将本地项目上传至gitee的详细步骤

将本地项目上传至gitee的详细步骤 1.在gitee上创建以自己项目名称命名的空项目2.进入想上传的项目的文件夹&#xff0c;然后右键点击3. 初始化本地环境&#xff0c;把该项目变成可被git管理的仓库4.添加该项目下的所有文件5.使用如下命令将文件添加到仓库中去6.将本地代码库与远…

ArcGISPro中如何使用机器学习脚本

点击工程 打开包管理器&#xff0c;我们可以发现&#xff0c;无法修改ArcGIS自带的默认python环境&#xff0c;所以我们需将默认环境进行克隆 点击设置 设置要克隆的地方&#xff0c;点击确定 激活克隆的环境&#xff0c;然后重写启动ArcGISPro 搜索并点击需要安装的库&#xf…

【字典学习+稀疏编码Sparse Encoding】简单介绍与sklearn的实现方式

文章目录 1、字典学习与稀疏编码2、sklearn的实现3、示例 1、字典学习与稀疏编码 简单来说&#xff0c;稀疏编码就是把输入向量&#xff08;信号&#xff09;/ 矩阵&#xff08;图像&#xff09;表示为稀疏的系数向量和一组超完备基向量&#xff08;字典&#xff09;的线性组合…

机器学习-特征选择:如何使用递归特征消除算法自动筛选出最优特征?

一、引言 在实际应用中&#xff0c;特征选择作为机器学习和数据挖掘领域的重要环节&#xff0c;对于提高模型性能和减少计算开销具有关键影响。特征选择是从原始特征集中选择最相关和最具区分力的特征子集&#xff0c;以提高模型的泛化能力和可解释性。 特征选择在实践中具有以…

无涯教程-Perl - sethostent函数

描述 该函数应在首次调用gethostent之前调用。 STAYOPEN参数是可选的,在大多数系统上未使用。 当gethostent()检索主机数据库中下一行的信息时,然后sethostent设置(或重置)枚举到主机条目集的开头。 语法 以下是此函数的简单语法- sethostent STAYOPEN返回值 此函数不返回…

语雀真的那么好用吗?那是你还没试试Baklib在线知识库/帮助中心

其实他们都是非常好用的在线知识库和协作工具。它提供了丰富的功能和友好的用户界面&#xff0c;让用户可以方便地管理和共享知识。 语雀的使用感受&#xff1a; 首先&#xff0c;语雀具有简洁、直观的界面设计&#xff0c;使得用户能够快速上手。它采用了扁平化的设计风格&a…

冠达管理:险资最新重仓股曝光!加仓这些股票

随着上市公司半年报陆续发表&#xff0c;险资最新重仓持股状况也逐渐清晰。 到8月14日&#xff0c;在已发表2023年半年报的上市公司中&#xff0c;超越60家上市公司的前十大流通股东中呈现险资身影。 从职业来看&#xff0c;制造业成为险资的“心头好”。在险资重仓个股中&…

npm install 中 --save 和 --save-dev 是什么?

npm&#xff0c;全名 Node Package Manager&#xff0c;套件管理工具&#xff0c;package.json 会记下你在项目中安装的所有套件。 假设在项目中安装 lodash npm i --save lodash这样在 dependencies 中会出现&#xff1a; 如果修改了导入方式&#xff1a; npm i --save-dev …

【华为Datacom 综合拓扑案例—分享篇】

拓扑图 题目要求 实验要求&#xff1a; 1、PC1\PC2\PC3\PC4采用DHCP自动获取IP地址&#xff0c;SW5作为服务器&#xff0c;SW3和SW4作为中继 创建地址池ip pool huawei1和ip pool huawei2&#xff0c;租期都为2天 2、SW3与SW4做链路聚合&#xff0c;采用LACP模式。SW3作为主…

【C语言】每日一题(寻找数组的中心下标)

寻找数组的中心下标&#xff0c;链接奉上 方法 暴力循环前缀和 暴力循环 ​​​​​​​思路&#xff1a; 依旧是我们的老朋友&#xff0c;暴力循环。 1.可以利用外层for循环&#xff0c;循环变量为数组下标&#xff0c;在循环内分别求出下标左边与右边的sum 2.在边界时讨论&…

使用 NLP 进行文本摘要

一、说明 文本摘要是为较长的文本文档生成简短、流畅且最重要的是准确摘要的过程。自动文本摘要背后的主要思想是能够从整个集合中找到最重要信息的一小部分&#xff0c;并以人类可读的格式呈现。随着在线文本数据的增长&#xff0c;自动文本摘要方法可能会非常有用&#xff0c…