"泛"就是广泛的意思,"型"就是数据类型。顾名思义,泛型就是适用于多种数据类型的一种类型。
它能够帮助我们构建出复用性更强的代码
- function getResult(value: number): number {
- return value
- }
例如,我们希望传参类型和函数返回类型一致时。我们可以使用泛型。
- function getResult
(value: T): T { - return value
- }
在定义一个函数时,不决定这些参数的类型,而是让调用者以参数的形式告知函数参数应该是什么类型。
函数定义时,<>的位置就是泛型的传入位置,比如上面函数的
getResult
(100) // 泛型收缩为数字 sum<{name: string}>({ name: "zs" }) // 泛型收缩为引用对象
或者我们可以让TS通过类型推导 自动识别:
getResult(100)
sum({ name: "zs" })
泛型类型不是一定要使用T来表示类型。只是大家常用T表示类型。
TS允许引入希望定义的任何名字的类型变量。比如我们引入一个新的类型变量 U,重写上面getResult方法。
- function getResult(val:U):U{return val}
- getResult<number>(100)
同时引入希望定义的任何数量的类型变量
- function sumNew(val:U,count:A):number{return 300}
- sumNew(3,'ss')
在定义接口的时候也可以使用泛型来对接口内的成员进行类型约束。
- interface IInfo
{ - name: T1
- age: T2
- }
使用泛型接口:
- const info: IInfo<string, number> = {
- name: "zs",
- age: 25
- }
泛型接口有类型默认值但是没有类型推导(函数传参不能使用,但是函数传参有类型推导)
- // 泛型接口定义默认类型
- interface IPerson
string, T2 = number> { - name: T1
- age: T2
- }
-
- const p: IPerson = {
- name: "chenyq",
- age: 123
- }
类型推导报错:
- class Point
{ - x: T
- y: T
- z: T
-
- constructor(x: T, y: T, z: T) {
- this.x = x
- this.y = y
- this.z = y
- }
- }
- // 泛型类自动推导类型
- const point1 = new Point("1.33.2", "2.22.3", "4.22.1")
- // 泛型类明确泛型类型
- const point2 = new Point<string>("1.33.2", "2.22.3", "4.22.1")
const point3: Point<string> = new Point("1.33.2", "2.22.3", "4.22.1")
- // 定义字符串数组
- const arr1: string[] = ["a", "b", "c"]
- const arr2: Array<string> = ["a", "b", "c"]
泛型除了指定具体类型,还可以通过某类特征指定类型。
比如string和array都是有length的,或者某些对像也是会有length属性的。
我们想写一个函数,只接受含有length属性的参数,该怎么写?
定义一个接口,指定length属性
- interface hasLength {
- length: number
- }
用一个继承hasLength的接口做泛型约束:
- function fn
(arg:T) { - console.log(arg)
- }
- function fn
extends hasLength> (arg:T) { - console.log(arg)
- }