持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情
1. 引言
什么是泛型?泛型有什么作用?在什么场景使用它呢? 今天我们来介绍下泛型,这个是类型系统中一个重要知识点。 我们引用下官方Ts文档介绍:
软件工程中,我们不仅要创建一致的定义良好的 API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。
在像 C# 和 Java 这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。
2. 含义
首先,我们先来了解下官方变量名词:
T:(Type)官方泛型变量名词,表示任何类型(也就是我们常说的泛型)
K:(Key)官方键值变量名词,表示对象中的类型
V:(Value)官方值变量名词,表示对象中的值的类型
E:(Element)表示元素类型
模板例句:
function identity <T>(value: T) : T { return value }
解析如上:第一个泛型变量通过链式传递给参数类型(第二个T)和返回值类型(第三个T)
在使用上我们可以使用两种方式
- 直接定义要使用的类型
- Ts类型推断,自动帮我们推断类型
3. 作用
泛型简单来说就是对类型编程,当需要使用到的场景值,以及返回值是灵活多变的时候就可以使用泛型定义,它就像是一个占位符(当然在这里我们并不考虑使用any类型,因为总所周知any类型是类型系统的“万精油”,“漏洞”,专门用来逃避类型检测的,且不说写 any 类型不好,毕竟在 TS 中尽量不要写 any。),这样减少当一些场景重复定义大致相同类型,减少代码体量 请看例子一。
在类型定义使用过程中我们还可以给泛型加默认参数(请看例子二) 它有个重要方法:泛型方法定义约束(请看例子四)
4. 例子
例子一:避免因为不确定的行参类型重复的定义函数接收就想下面这样
function printFun(lineVal:string):string {
return lineVal
}
function printFun(lineVal:string | number):string | number {
return lineVal
}
// 或者直接使用这样暴力的方式,直接使用any
function printFun(lineVal:any):any {
return lineVal
}
// 使用泛型一步搞定,T可以是调用时传入的任意形参,这样就做到了输入和输出的类型统一,且可以输入输出任何类型。
function print<T>(arg:T):T {
return arg
}
例子二:
interface Iprint<T = number> {
(arg: T): T
}
function print<T>(arg:T) {
return arg
}
const myPrint: Iprint = print
例子三:
function tupleFun<T, U>(tuple: [T, U]): [U, T]{
return [tuple[1], tuple[0]]
}
例子四:
interface Getlength {
length: number
}
function printLength<T extends Getlength>(arg: T): T {
return arg
}
const str = printLength('lin')
const arr = printLength([1,2,3])
const obj = printLength({ length: 10 })
5. 总结
一。泛型的使用,是为了可以在定义函数、接口或类的时候,不预先指定具体类型,而是在使用的时候再指定类型。减少重复定义代码,支持多种类型,提高扩展性,不必通过例子一中亢长的联合类型来定义,就像一个占位符、或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,它可以原封不动地输出。 二。泛型在:函数形参参数、函数返回值、类的实例成员、类的方法等提供了约束的方式。