TypeScript - 泛型
前言
本文主要记录下 TypeScript 泛型知识点,日常学习总结篇。
一、概念
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
二、例子
首先来看一个简单的例子,体会一下泛型可解决的问题。
需求:定义一个 identity 函数,这个函数会返回任何传入它的值。如传入参数的类型是 number,函数返回类型为 number。
function identity(arg: number): number {return arg;
}
然后,需求变更,传入参数类型可以是 string,函数返回类型也是 string。
此时可以使用联合类型实现需求,代码如下。
function identity(arg: number | string): number | string {return arg;
}
然后需求再次变更,传入的参数类型可以支持更多类型,甚至任何类型时,如何实现呢?
此时可以使用 any 类型来定义函数,代码如下。
function identity(arg: any): any {return arg;
}
使用 any
类型会导致这个函数可以接收任何类型的 arg
参数,但是这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。
例如传入一个 number 类型的参数,使用 string 类型来接收函数的返回值,此时 TS 并不会报错提示我们。代码如下。
const value: string = identity(89)
这时候,泛型就派上用场了。代码如下。
function identity<T>(arg: T): T {return arg
}
这样就可以做到函数传入的类型与返回的类型一致,而且可以传入返回任何类型。
如果类型不一致,TS 就会报错。
三、泛型基本使用
泛型的语法是 <>
里写类型参数,一般可以用 T 来表示。T 表示 Type,实际上 T 可以用任何有效的名称代替。除了 T 之外,常见的泛型变量还有 K、V 和 E 等。
- K(key):表示对象中的键类型;
- V(value):表示对象中的值类型;
- E(element):表示元素类型。
泛型中的 T 被称为泛型变量,或者说一个类型占位符。就像传递参数一样,在使用的时候把指定的实际类型,链式传递给参数类型和返回值类型。
在使用的时候,可以有两种方式指定类型:
- 定义具体类型;
- TS 类型推断,自动推导出类型。
identity<string>('abc') // 定义具体类型identity(123) // TS 类型推断,自动推导出类型
四、处理多个泛型参数
需求:定义一个函数,传入一个只有两项的元组类型数据,交换元组的值的顺序,返回这个元组。
实现代码如下:
function swap<T, U>(tuple: [T, U]): [U, T]{return [tuple[1], tuple[0]]
}
传入一个参数,定义元组第 0 项为 string 类型,第 1 项为 number 类型。
const arr = swap<string, number>(['abc', 123])
得到的函数返回值,第 0 项为 number 类型,第 1 项为 string 类型。
第 0 项上全是 number 类型的方法,如下图所示。
第 1 项上全是 string 类型的方法,如下图所示。
五、泛型接口
定义接口时, 为接口中的属性或方法定义泛型类型,在使用接口时, 再指定具体的泛型类型。
interface ICreateObj<K, V> {name: K,age: V
}const obj: ICreateObj<string, number> = {name: 'jenny',age: 18
}
六、泛型类
在类中使用泛型也很简单,只需要在类名后面,使用 <T, ...>
的语法定义任意多个类型变量。
class GenericFn<T> {defaultValue: T;add: (a: T, b: T) => T
}// 传入 number 类型
const genericNumber = new GenericFn<number>()
genericNumber.defaultValue = 6
genericNumber.add = (x, y) => x + y
genericNumber.add(genericNumber.defaultValue, 8) // 14// 传入 string 类型
const genericString = new GenericFn<string>()
genericString.defaultValue = 'a'
genericString.add = (a, b) => a + b
genericString.add(genericString.defaultValue, 'c') // ac
七、默认参数
在 TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推断出类型时,这个默认类型就会起作用。
泛型参数默认类型与普通函数默认值类似,对应的语法很简单,即 <T=Default Type>
,对应的使用示例如下:
function identity<T = string>(arg: T): T {return arg
}
八、泛型约束
在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法。
需求:实现一个函数,打印出传入参数的长度。
可以这样实现:
function getLength<T>(arg: T): T {console.log(arg.length)return arg
}
上例中,泛型 T
不一定包含属性 length
,所以编译的时候 TS 会提示错误,类型 T 上不存在属性 length。如下图:
这时,就可以对泛型进行约束,只允许这个函数传入那些包含 length
属性的变量。
interface ILength {length: number
}function getLength<T extends ILength>(arg: T): T {console.log(arg.length)return arg
}
上面代码中,最关键的就是 <T extends ILength>,让泛型 T 继承接口 ILength,也就是传入的参数类型必须包含 length
属性,这样就能约束泛型。
此时再次调用 getLength 函数的时候,传入的参数 arg 如果不包含 length 属性,那么在编译阶段 TS 就会报错。如下图所示。
此外,还可以使用 ,
号来分隔多种约束类型,比如:<T extends Type1, Type2, Type3>
。
TypeScript - 泛型相关推荐
- 泛型 typescript_如何把你的头围绕Typescript泛型
泛型 typescript by Nadeesha Cabral 通过Nadeesha Cabral 如何把你的头围绕Typescript泛型 (How to wrap your head aroun ...
- TypeScript泛型约束
泛型约束 有了泛型之后,一个函数或容器类能处理的类型一下子扩到了无限大,似乎有点失控的感觉.所以这里又产生了一个约束的概念.我们可以声明对类型参数进行约束. 我们还拿上文中的student栗子来说,想 ...
- TypeScript泛型详解
泛型 泛型(Generics)是指在定义函数.接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性. 示例 我们先实现一个student方法获取不同属性来看看使用: JavaScr ...
- TypeScript泛型工具
Required 将类型的属性变成必选 interface Person {name?: stringage?: numberhobby?: string[] }// 下面的类型不用定义, TypeS ...
- TypeScript 泛型T使用整理
一.介绍 相C#和Java等以上,TypeScript可以使用泛型来创建可重用的组件.支持当前数据类型,同时也能支持未来的数据类型.扩展灵活. 二.泛型的定义.使用 使用泛型可以创建泛型函数.泛型接口 ...
- 【TS】1368- 秒懂 TypeScript 泛型工具类型!
阿宝哥精心准备的<轻松学 TypeScript> 视频教程已经更新到第十九期了,合集播放量已达 14W+.通过形象生动的动画,让你轻松搞懂 TypeScript 的难点和核心知识点! 如果 ...
- TypeScript 泛型
TS里面有泛型让我很意外,这个比AS3确实要强大: let myIdentity_change : <T>(arg:T)=>T=function(a){ return a };con ...
- TypeScript泛型
泛型的概念 指不预先确定的数据类型,具体的类型要在使用的时候才能确定.咋一听,是不是觉得JavaScript本身就是这样?这是由于理解有误.前面说"在使用的时候确定",而非在程序执 ...
- Typescript泛型与implements子句
一.泛型的基本使用 与extends的区别 泛型可以理解为宽泛的类型,通常用于类和函数.使用的时候我们再指定类型 泛型不仅可以让我们的代码变得克加健壮,还能让我们的代;码在变得键壮的r时保持灵活性和可 ...
最新文章
- oracle 与 client端执行结果不一致_不同模式下Spark应用的执行过程
- 小程序制作五星点评(默认五星)
- python判断几个数最大最小_python 找出list中最大或者最小几个数的索引方法
- JAVA Spring 事物 ( 已转账为例 ) 基于 AOP 注解
- 云服务器php版本修改,云服务器 更改php版本
- git提交到github总是要输入密码_GitHub不为人知的秘密
- libsvm在matlab中使用的常见错误及libsvm的使用
- Chrome浏览器V43版本不支持silverlight 5.0的解决办法
- IAT 注入ImportInject(dll)
- Ubuntu下利用python实现自动打卡系统全过程
- Android 截屏监听分享
- CPU飙高原因及解决方案
- Android Killer反编译时遇到的异常
- Git超详解七 储藏 (看不懂算我输)
- XILINX XC7A200T-1FBG676C FPGA - 现场可编程门阵列
- 检测特殊字符的正则表达式
- Java读取word模板,并动态生成word
- infer.net 入门2 用一个侦探故事来讲解,通俗易懂
- 【分享】许多 有意思的 颜文字表情包
- 金博医药WMS仓储管理系统的功能特点
热门文章
- req.on 和req.body的使用
- 一次维修打印机复印件的记录
- excel函数公式加减乘除
- 【IoT】寻光智能车与循迹智能车
- SpringBoot中 判断上传的文件类型 MultipartFile file
- python正则表达式匹配网址中的域名_正则表达式匹配域名、网址、url
- 导入cx_Oracle时提示DLL load failed问题解决
- 互联网应届毕业生简历心得
- matlab %4.3f,MATLAB程序设计教程(4)—MATLAB文件操作
- 基调网络提供网页首屏监测技术 助力互联网应用企业提升网站性能