泛型Generics,是指在定义函数Function、接口Interface 或类 Class 时不预先指定具体的类型,而是在使用的时候再指定类型的一种特征。
// 函数名后的 <> 内传入泛型参数,在使用时指定类型
function echo<T>(arg: T): T {
return arg
}
const str: string = 'str'
const result = echo(str) //类型推论会推论出参数的类型
泛型可以看作是类型变量,它是一种特殊的变量,只用于表示类型而不是值。在使用时把类型像参数一样传入。
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]]
}
const result2 = swap(['string', 123])
results[1].fixed() // 可以调用Number方法
约束泛型-函数(在函数的参数和返回值中使用泛型)
有时候想操作某类型的一组值,并且我们知道这组值具有什么样的属性。 在 下面例子中,我们想访问arg
的length
属性,但是编译器并不能证明每种类型都有length
属性,所以就报错了。
function loggingIdentity<T>(arg: T): T {
console.log(arg.length); // Error: T doesn't have .length
return arg;
}
相比于操作any所有类型,我们想要限制函数去处理任意带有.length
属性的所有类型。 只要传入的类型有这个属性,我们就允许,就是说至少包含这一属性。 为此,我们需要列出对于T的约束要求。
为此,我们定义一个接口来描述约束条件。 创建一个包含 .length
属性的接口,使用这个接口和extends
关键字来实现约束:
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // Now we know it has a .length property, so no more error
return arg;
}
// 现在这个泛型函数被定义了约束,因此它不再是适用于任意类型:
loggingIdentity(3); // Error, number doesn't have a .length property
// 我们需要传入符合约束类型的值,必须包含必须的属性:
loggingIdentity({length: 10, value: 3});
loggingIdentity([1, 2, 3]);
loggingIdentity('string');
约束泛型-类 Class
// 队列类-先进先出
class Queue {
private data = []
push(item) {
return this.data.push(item)
}
pop() {
return this.data.shift()
}
}
// 实例化类
const queue = new Queue()
queue.push(1)
queue.push('str')
console.log(queue.pup().toFixed()) // 1
// string 类型并无toFixed 方法
console.log(queue.pop().toFixed()) // Error:...toFixed is not a function
/*-- 解决以上问题需要为该类添加泛型约束 --*/
class Queue<T> {
private data = []
push(item: T) {
return this.data.push(item)
}
pop(): T {
return this.data.shift()
}
}
// 实例化类-添加实例类型 number
const queue = new Queue<number>()
queue.push(1)
// queue.push('str') // 已不符合约定的类型
console.log(queue.pop().toFixed()) // 1
// string 类型并无toFixed 方法
console.log(queue.pop().toFixed()) // Error:...toFixed is not a function
// 实例化类-添加实例类型 string
const queue = new Queue<string>()
queue.push(1)
console.log(queue.pop().length) // 1
约束泛型- Interface
interface KeyPair<T, U> {
key: T;
value: U;
}
let kp1: KeyPair<number, string> = { key: 123, value: 'str'}
let kp2: KeyPair<string, number> = { key: 'str', value: 123}
let arr: number[] = [1, 2, 3]
let arrTwo: Array<number> = [1, 2, 3]
在interface 函数中使用泛型
interface IPlus<T> {
(a: T, b: T): T
}
function plus(a: number, b: number): number {
return a + b
}
function connect(a: string, b: string): string {
return a + b
}
const a: IPlus<number> = plus()
const b: IPlus<string> = connect()