在开发的场景中,如果我需要写二三个指定的返回类型,虽然可以用联合类型,但是还是不够优化。比如number| string | boolean。看起来写的有点麻烦!于是Typescript有了泛型,那什么是泛型呢?简单地来说,使用了泛型,比如使用泛型类型为T,那么可以捕获用户传入的类型是什么,然后把泛型T设置为它指定的类型。比如:用户传入的类型是number,那返回类型是number。这样支持多个类型(传入任何的类型可以自动帮助我们推断哪个指定的类型),泛型非常十分灵活而且重用性高。我们如何使用泛型,如下
1.基础泛型
(1)非泛型
function gend(a:string,b:string):Array<string>{
return [a,b]
}
function gend(a:number,b:number):Array<number>{
return [a,b]
}
可以看到,这同二个函数支持多个类型,可见重用性很差的。
(2)泛型
function gend<T>(a:T,b:T):Array<T>{
return [a,b]
}
gend(1,2) // [1,2]
gend(true,false) // [true,false]
gend('hong','huang') // ['hong','huang']
在函数被调用的时候采用了数字、布尔以及字符串类型,泛型可以支持多个类型,帮我们自动推断返回哪个是指定的类型。在开发时候,如果类型不明确的话,千万别用any类型,使用any类型的时候有一些会丢失信息。所以一般可以使用泛型。
2.泛型-变量
虽然泛型是通用性类型,有些在使用泛型的时候,想返回长度类型,可能会出现问题,比如:
function dent<T>(num:T):T{
console.log(num.length)
return num
}
在打印的时候,这样会报错的,因为变量是没有长度属性。泛型函数传入默认是数字类型,但是数字类型是没有长度属性。我们来如何写正确使用泛型,如下:
function dent<T>(num:T[]):T[]{
console.log(num.length)
return num
}
或者是
function dent<T>(num:Array<T>):Array<T>{
console.log(num.length)
return num
}
以上的使用泛型并正常地返回数字长度属性。
3.泛型-类型
其实非泛型与泛型区别不大,只有在函数前面加个类型T。
(1)非泛型
function an(num){
return num
}
// =》
let an1:(num:any)=>any= an
(2)泛型
function an<T>(num:T):T{
return num
}
// =》
let an1:<T>(num:T)=> T = an
可以看到,不同在于函数前面添加类型T。
(3)支持不同参数名
function an<T>(num:T):T{
return num
}
let an1:<Q>(num:Q)=> Q = an
这两者存在不同的泛型参数名,这样可以相等的。
(4)对象字面量
function qna<T>(str:T):T{
return str
}
let qna1:{<Q>(str:Q):Q} = qna
泛型类型也可以支持对象字面量,也是可以相等的。
4.泛型-类
其实与泛型接口看起来没什么不同,我们来看如何使用:
(1)泛型接口
interface obj{
(b:T):T
}
let b : obj<string>
相当于(b:string)=>string的函数
(2)泛型-类
interface info<T,Q>{
name:T,
age:Q
}
let a = new info<string,number>()
a.name = xiaobin"
a.age = 18
调用的时候,这样可以在实例化再指定的具体类型。
5.泛型-约束
虽然泛型是太广且不是万能的,尽量去控制约束泛型类型。可以使用这样写如下:
function zfs<T extends number>(a:T,b:T){
return a+b
}
zfs(3,4)
另外,如果我写需要返回输出为数组长度,比如:
function zfs<T>(arr:T):number{
return arr.length
}
其实这是报错的,为什么?因为输出数字类型,且没有length属性。只有数组才有length数组。对象、字符串等都是没有length属性。要保证传入类型必须正确地使用length属性,只有接口加上extends传承关键字来实现约束。
infaceter Arr{
length:number
}
function arrLength<T extends Arr>(arr:T){
return arr.length
}
// arrLength('123123')
// arrLength([2,32,3])
// arrLength(1234124) //类型报错,字符串没有length属性
// arrLength(false) //类型报错,布尔没有length属性