持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情
接着之前的TypeScript系列文章,今天来学习TypeScript中的泛型。
泛型
指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。
<T> – T 被称为类型参数
泛型(Generics)允许同一个函数接受不同类型参数。相比于使用 any 类型,使用泛型来创建可复用的组件要更好,因为泛型会保留参数类型,保持代码的灵活性和可重用性。
简单举例说明:泛型函数
根据指定的数量
count(number类型) 和数据value(不预先指定具体类型) ,创建一个指定长度的数组。
在creatArray函数名后添加了 <T> (也可以是其他别的字母),其中 T 用来指代任意输入的类型,在函数内部就可以使用这个 T 类型(即在后面的输入 value: T 和输出 Array<T> 中使用)
const creatArray = <T>(value: T, count: number = 2) => {
const arr: Array<T> = []
for(let i = 0; i < count; i++){
arr.push(value)
}
return arr
};
// 指定具体类型调用
const arr1 = creatArray<number>(11)
console.log(arr1) // [11, 11]
// ts做类型推论自动推算出来具体类型(根据传递的泛型参数)
const arr2 = creatArray('aa')
console.log(arr2) // ['aa','aa']
泛型变量
常见泛型变量:(只是一个约定好的规范,使用其它大写字母也可以)
- T(Type):表示一个 TypeScript 类型
- K(Key):表示对象中的键类型
- V(Value):表示对象中的值类型
- E(Element):表示元素类型
泛型接口
在定义接口时, 为接口中的属性或方法定义泛型类型。在使用接口时, 再指定具体的泛型类型
interface Person<T> {
name: string;
like: T;
}
// 本例中传入的“like”类型是字符串数组
const person1: Person<string[]> = {
name: 'ConardLi',
like: ['apple', 'banana', 'watermelon'],
}
//本例中传入的“like”类型是一个字符串
const person2: Person<string> = {
name: 'Tom',
like: 'pomegranate',
}
泛型类
与泛型接口类似,泛型也可以用于类的类型定义中
class enumeration<T> {
arr:T[] = [];
add(value:T):T{
this.arr.push(value);
return value;
}
all():T[]{
return this.arr;
}
}
let number = new enumeration<number>();
number.add(1);
number.add(3);
number.add(5);
console.log(number.all()); // [1,3,5]
泛型约束
在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法。
默认情况下我们可以指定泛型为任意类型,但是有些情况下指定的类型需要满足某些条件,那么这个时候我们就可以使用泛型约束来实现
简单举例说明:获取一个参数的长度
对一个泛型参数取
length属性, 会报错, 因为这个泛型T不一定包含属性length使用泛型约束,使用
extends约束泛型<T>必须符合LengthInterface的形状,也就是必须包含length属性
interface LengthInterface{
length:number
}
let getLength = <T extends LengthInterface>(value:T):T=>{
console.log(value.length); // 4
return value;
};
getLength('1234');
//getLength(7); //报错:number没有length属性