定义
泛型允许我们在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些类型。在ts中,定义函数、接口或类的时候,不预先定义好具体的类型,而在使用的时候在指定类型的一种特性。
例子:
我们要实现一个类似echo
的函数,输入什么就输出什么,需要确保输入和输出的类型相同,并且支持多个类型
function identity<T>(arg: T): T {return arg;
}
console.log(identity(123))
console.log(identity(true))
console.log(identity('aaa'))
console.log(identity({a:1}))
let output2 = identity<string>("myString");
可以自动添加类型
也可以指定类型
使用
泛型通过<>
的形式进行表述,可以声明函数、接口、类。
函数声明
多参数泛型类型
// function swap<K, U>(a: K, b: U): [U, K] {
// return [b, a]
// }
function swap<K, U>(a: K, b: U): Array<K | U> {return [b, a]
}
console.log(swap(3,'44'))
接口声明
定义接口时,在名字后加一个参数
interface ReturnData<T> {(param: T): T
}
const returnItem: ReturnData<number> = param => param
console.log(returnItem(5))
类声明
与接口一样,直接把泛型类型放在类后面,可以帮助我们确认类的所有属性都在使用相同的类型。
我们在类那节说过,类有两部分:静态部分和实例部分。 泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型
class Stack<T>{private arr: T[] = []public push(item: T) {this.arr.push(item)}public pop(item: T) {this.arr.pop()}
}let a = new Stack<string>()
a.push('b')let b = new Stack<number>()
b.push(22)
泛型约束
extends
我们想访问arg
的length
属性,但是编译器并不能证明每种类型都有length
属性,所以就报错了,要限制函数去处理任意带有.length
属性的所有类型。
keyof
再泛型约束中使用类型参数。声明一个类型参数,且他被另一个类型参数所约束。比如,现在我们想要用属性名从对象里获取这个属性。
首先定义了T类型并用extends
关键字继承object
类型的子类型,然后使用keyof
操作符获取T类型的所有键,他的返回类型是联合类型,最后利用extends
关键字约束K类型为keyof T
联合类型的子类型