泛型
我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能
泛型之hello world
不使用泛型
function indentity(arg: number): number {
return arg
}
function identity(arg: any): any {
return arg;
}
使用any类型会导致这个函数可以接收任何类型的arg参数,这样就丢失了一些信息:传入的类型与返回的类型应该是相同的。如果我们传入一个数字,我们只知道任何任性的值都有可能被返回
因此,我们需要一种方法使返回值的类型与传入的参数的类型时相同的。
这里我们使用了类型变量,它是一种特殊的变量,只用于表示类型而不是值
// 类型变量T,
function indentity<T>(arg:T):T{
return arg
}
T帮助我们捕获用户传入的类型,之后我们就可以使用这个类型。
现在我们可以知道参数类型与返回值类型时相同的了。这允许我们跟踪函数里使用的类型的信息
let output = identity<string>('sss')
let output = identity<number>(1)
使用泛型变量
如果你需要在函数内部使用参数的length属性,可以这样使用
// 会报错,因为T可能是number,number没有length属性
function loggingIdentity<T>(arg: T): T {
console.log(arg.length); // Error: T doesn't have .length
return arg;
}
function loggingIdentity<T>(arg: T[]): T[] {
console.log(arg.length); // Array has a .length, so no more error
return arg;
}
// 或者
function loggingIdentity<T>(arg: Array<T>): Array<T> {
console.log(arg.length); // Array has a .length, so no more error
return arg;
}
泛型类型
- 泛型函数的类型与非泛型函数的类型没有什么不同,只是有一个类型参数在最前面
function identity<T>(arg: T):T {
return arg
}
let myIdentity: <T>(arg: T) => T = inentity
// 或
let myIdentity: {<T>(arg: T) => T} = inentity
myIdentity(10) // 10
- 泛型接口
interface IIdentityFn{
<T>(arg:T):T
}
function identity<T>(arg:T):T {
return arh
}
let myIdentity: IIdentityFn = identity
- 把泛型的参数当做接口的参数
interface IIdentityFn<T> { (arg:T):T } function identity<T>(arg: T): T { return arg; } let myIdentity: IIdentityFn<number> = identity
注意:以上示例,不在描述泛型函数,而是把非泛型函数签名作为泛型类型的一部分。当我们使用IIdentityFn的时候,还得传入一个类型参数来执行反省了类型(这里是number),锁定了之后代码里使用的类型。
泛型类
泛型类看上去与泛型接口差不多。 泛型类使用(<>)括起泛型类型,跟在类名后面
class Gener<T> {
zero: T
add: (x: T, y:T) => T // T类型的x,y参数 返回T类型的值
}
let myGen = new Gen<number>()
myGen.zero = 0
myGen.add = function(x,y) {
return x+y
}
泛型约束
interface LenWise {
length: number
}
function loggingIden<T extends LenWise>(arg: T) {
console.log(arg.length)
return arg
}
在泛型约束中使用类型参数
你可以声明一个类型参数,且她被另一个类型参数所约束。比如,
function getProperty(obj: T, key: K) {
return obj[key]
}
let x = {a:1, b:2, c:3}
getProperty(x, 'a')
getProperty(x, 'm')