泛型
不仅要创建一致定义良好的API,同时要考虑可重用性。组件不能支持当前的数据类型,同时也能支持未来的数据类型,可为此提供十分灵活的功能。
可使用泛型来创建可重用的组件,一个组件可支持多种类型的数据。
不用泛型的代码:
function ident(arg:any):any { // any 为任意类型
return arg
}
用any 很容易丢失一些信息:传入的类型和返回的类型应该是相同的。如果我们传入一个数字,我们只知道任何类型的值都有可能被驳回。
我们需要一种方法使返回值的类型与传入参数类型是相同的。使用类型变量,它是一种特殊的变量,只用于表现类型而不是值。
function ident <T>(arg:T):T {
return arg
}
T帮助我们捕获用户传入的类型,我们可以使用这个类型。之后我们再次使用了T当做返回类型。就能知道参数类型和返回类型是相同的。允许我们跟踪函数里使用的类型的信息。
我们把这个版本的ident叫做泛型,因为他可以使用多个类型。不同于any,不会丢失信息,保持准确性,传入数值类型并返回数值类型。
定义泛型函数后,可以有两种方法使用。
第一种,传入所有的参数,包含类型参数:
let output = ident<string>('myString') // output 是string
T是string类型,并做为一个参数传给了函数,使用了<>而不是( )
第二种方法更普遍。利用了类型推论—-编译器会根据传入的参数自动的帮助确定的类型:
let output = ident('myString')
没必要使用<>来明确传入的类型,编译器可以查看myString的值,然后把T设置为它的类型。如果不能够自动的推断出类型的话,只能明确的传入T的类型,在一些复杂的情况下,是可能出现的。
使用泛型变量
function ident<T>(arg:T):T{
consel.log(arg.length)
return arg
}
// 此时会报错,arg有可能是数字类型没有length
操作T类型的数组不直接是T。由于我们操作的是数组,所以.length属性是应该存在的。我们可以像创建其他数组一样创建这个数组:
function logging<T>(arg:T[]):T[] {
consel.log(arg.length)
return arg
}
泛型类型
泛型函数的类型与非泛型函数的类型没什么不同,只是有一个类型参数在最前面,像函数声明一样:
function ident<T>(arg:T):T {
return arg
}
let myIdentity:<U>(arg:U) => U = ident
// 可以使用不同的泛型参数名,只要在数量上的使用方式上能对应上就可以