泛型
泛型(Generics),可以理解为类型参数。它的核心思想是,在定义函数、接口、类和别名时以参数的形式表示类型,在调用的时候传入具体的类型。
如何使用泛型?
语法:在名称后面使用尖括号 <T> 来声明泛型类型参数,(T 是 Type 的含义,也可以用 U、K 等)
在函数中使用
在函数名称后定义
typescript
// 将传入的参数返回
function identity<T>(arg: T): T {
return arg;
}
// 两种调用方式:
// 1. 显式指定类型
const output1 = identity<string>('hello')
// 2. 类型推断(推荐)
const output2 = identity("hello"); // TS 自动推断 T 为 string在接口、类和别名的使用也一样,在名称后面定义:
typescript
// 接口
interface Box<T> {
value: T
}
const numberBox: Box<number> = { value: 42 };
// 类
class Container<T> {
private data: T;
constructor(value: T) {
this.data = value;
}
getData(): T {
return this.data;
}
}
const numContainer = new Container<number>(100);
const strContainer = new Container("hello");泛型类
泛型不能用于静态成员(因为静态成员属于类本身,而不是实例,而泛型是在实例化时确定的)。
泛型约束
有时我们希望泛型满足某些条件,比如必须有某个属性,这个时候会出现这样一个问题:
typescript
function getLength<T>(o: T): T {
return o.length // ❌ 无法确定o是否有length属性
}这个时候,我们可以使用 extends 对泛型进行约束。
typescript
interface LengthProps {
length: number
}
function getLength<T extends LengthProps>(o: T): T {
return o.length // ✅ 可以确保o有length属性,并且有ts提示
}
const length1 = getLength("hello"); // ✅ string类型有length属性
const length2 = getLength([1]); // ✅ array类型有length属性
const length3 = getLength(1); // ❌ number类型没有length属性