开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
泛型
-
把运行时期的问题提到编译时期
-
在函数重载中,同一个函数参数类型是会不一样的。这种情况下就比较适合使用泛型。 在保证类型安全的前提下,让函数与多种类型一起工作实现复用
-
语法为函数名字后面跟一个<参数名> 参数名可以随便写 一般都是使用 T U K等
-
等于是像函数参数一样写了一个any类型的形参便可以接收任意类型的参数
play<T>(name:T){
console.log(typeof name)
}
play(111) //number
play("TiGa")//string
泛型约束
- 泛型在某些时候也没有那么好用,例如泛型接收一个字符串你想获得length属性这时候你会发现你无法拿到length属性并且报编译错误以及运行错误
//这种时候如果第一时间想到类型断言,说明学的不错,但是我们要说的是第二种方式
//通过对泛型进行约束,使泛型具备length属性
interface A {
length: number
}
function getlength<T extends A>(arr: T) {
console.log(arr.length);
}
getlength("dddd")
- 注意不要搞混,泛型约束只能通过extends关键字来实现接口
- 但是类上必须使用interface实现接口
使用keyof 关键字约束对象
- keyof 映射出一个联合类型
- keyof 关键字接收一个对象类型 生成其键名称的联合类型(对象中的所有键名)
//K 继承了T类型的联合类型 约束了范围
function prop<T, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
let obj = { a: 1, b: 2, c: 3 }
prop(obj, 'a')
prop(obj, 'd') //此时就会报错,因为继承的联合类型中不存在d
泛型类
- 在类后加上<类型> 这个类就变成了一个泛型类,需要在使用的时候传递类型过来
- 传递过来的类型在类中都可以用
class MyList<T> {
private lists: T[] = new Array();
public add( e:T):void {
this.lists.push(e);
}
public remove(e:T):void {
let index=this.lists.indexOf(e)
this.lists.splice(index,1);
}
}
let m1=new MyList<number>();
m1.add(1)
m1.add(2)
m1.add(3)
m1.add(4)
m1.add(5)
m1.remove(5)
console.log(m1); //[1,2,3,4]
泛型方法
与上面的基本类似
- 定义方法的同时加入泛型这个方法就是泛型方法
play<T>(name:T){
console.log(typeof name)
}
play(111) //number
play("TiGa")//string
泛型接口
- 需要指定类型
- 类型变量所有成员可见
interface Space<T>{
id:(value:T)=>T
ids:()=>T[]
}
let obj:Space<number>={
id(value){return value},
ids(){ return [1,2,3,4]}
}
obj.id(1)//1
obj.ids()//[1,2,3,4]
总结
使用泛型可以是我们写出来的 代码更加精简更加优雅,一定要经常用。这样才能快速掌握泛型的使用。有什么不足的地方欢迎指正。