泛型
介绍
在项目中,组件不仅能够支持当前的数据类型,也需要能支持未来的数据类型,泛型就是用来解决这个场景问题的
Hello World
不用泛型又要满足条件的话,函数可能是下面这样:
function fun(arg: number):any {
return arg;
}
但是使用any就相当于放弃了ts的类型检查,或者使用重载来实现,但是会使得代码严重冗余,我们需要一种更简洁的方法使传入参数的类型和返回类型一致,就可以使用泛型
function fun<T>(arg: T): T {
return arg;
}
使用尖括号并为函数参数和返回值都指定类型为T,这里T就是就是一个泛型;T具体是什么类型是在函数调用时才定义的。
fun<string>('str');
fun('str');
以上两种写法都是ok的,区别就是一个手动制定了传入值的类型,而另一个使用了ts的类型推断,让编译器根据传入值自动确定
泛型类
泛型类看上去与泛型接口差不多。
class Cat<T> {
name: T;
constructor(a:T){this.name = a}
say(a):T{return this.name};
}
let cat1 = new Cat<string>(567) //error
let cat2 = new Cat<string>('dahuang') //fine
let cat3 = new Cat<number>(567) //fine
cat2.say(); //string 'dahuang'
cat3.say(); //number 567
这不是一个很好的例子但是大致能说明情况,函数可以根据不同的入参进行不同的处理,也就是之间说道的重载,类中的方法就可以使用泛型来实现。泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。
泛型接口
首先重温下函数的接口
interface CatFn{
(name:string,leg:number):string
}
let cat:CatFn = function(n:string,l:number):string{
return `我叫${n},我有${l}条腿`
}
cat('dahuang',3)
如果想让他有时返回string,有时返回number就可以使用泛型来定义
interface CatFn{
<T>(arg:T): T;
}
let cat:CatFn = function<T>(arg:T):T{
return arg
}
cat<string>('dahung')
cat<number>(123)
或者也可以这么用
function Cat<T>(arg:T):T{
return arg
}
let cat1:CatFn<string> = Cat;
cat1('dahuang')
泛型约束
约束泛型就是由any变成有限类型,或者说满足接口条件,类型通过继承接口做出某些限制;描述看不明白直接看代码
interface Rule{
length: number;
}
function arrayLike<T extends Rule>(arg: T): T {
return arg;
}
//这里定义了约束,因此它不再是适用于任意类型:
arrayLike(3); // Error 因为number不包含指定的属性lenght
arrayLike({length: 3, value: 3}); //fine
arrayLike([1,2,3]); //fine