泛型
泛型把类型当作参数传入函数、接口与类型别名、类 等,在保持类型关系的前提下复用实现,避免为每种具体类型复制一份代码或退化成 any。
泛型函数与推断
function first<T>(arr: T[]): T | undefined {
return arr[0]
}
const n = first([1, 2]) // T 推断为 number- 可显式实例化:
first<number>([1, 2])。 - 多类型参数时推断可能「过宽」,必要时显式注解或加约束。
约束:extends
function keys<T extends object>(o: T) {
return Object.keys(o) as (keyof T & string)[]
}T extends U表示:T 必须是 U 的子类型。- 常与
keyof、索引访问类型T[K]组合,进入 高级类型。
默认类型参数
interface Box<T = string> {
value: T
}泛型接口与泛型别名
interface Result<T, E> {
ok: true
value: T
}
type AsyncOp<T> = () => Promise<T>与 接口与类型别名 的常规规则相同,仅多出类型实参列表。
泛型类
class Stack<T> {
private a = [] as T[]
push(x: T) {
this.a.push(x)
}
}静态成员不能使用类类型参数 T(除非另有声明),这是常见易错点。
常见误区
- 协变逆变:函数参数位置与返回值位置的子类型关系不完全对称;自定义复杂泛型 API 时需查手册或实验。
{}与object:作约束时含义不同(基础类型)。