TypeScript 泛型:<T> 类型参数与约束
TypeScript 的泛型机制让你能编写可重用、类型安全的代码,而无需提前锁定具体类型。核心在于 <T> 这种类型参数写法——它像一个“占位符”,在调用时才被替换成真实类型。
理解泛型的基本用法
-
定义 一个带泛型的函数,在函数名后加上
<T>:function identity<T>(arg: T): T { return arg; }这里的
T是类型变量,代表“任意类型”。函数接收一个T类型的参数,返回同样类型的值。 -
调用 该函数时,有两种方式指定
T的实际类型:- 显式指定:
identity<string>("hello") - 让 TypeScript 自动推断:
identity("hello")(此时T被推断为string)
- 显式指定:
-
应用 泛型到接口或类,实现更灵活的数据结构:
interface Box<T> { value: T; } const numberBox: Box<number> = { value: 42 }; const stringBox: Box<string> = { value: "text" };
使用类型约束限制泛型范围
默认情况下,T 可以是任何类型。但有时你需要确保 T 具备某些属性或方法,这时就要用 extends 关键字添加约束。
-
定义 一个约束接口,规定必须包含的成员:
interface Lengthwise { length: number; } -
修改 泛型函数,要求
T必须实现该接口:function logLength<T extends Lengthwise>(arg: T): T { console.log(arg.length); // 安全访问 length 属性 return arg; } -
调用 受约束的函数:
- ✅ 合法:
logLength("hello")(字符串有length) - ✅ 合法:
logLength([1, 2, 3])(数组有length) - ❌ 报错:
logLength(42)(数字没有length,编译失败)
- ✅ 合法:
多个类型参数与复杂约束
当需要处理多个相关类型时,可以声明多个泛型参数,并对它们分别或联合施加约束。
-
声明 两个类型参数
K和V,并约束K必须是对象键类型:function getProperty<K extends keyof T, T>(obj: T, key: K): T[K] { return obj[key]; }这里
keyof T表示T所有属性名的联合类型,确保传入的key是合法的属性名。 -
使用 该函数安全获取对象属性:
const person = { name: "Alice", age: 30 }; const name = getProperty(person, "name"); // 类型为 string const age = getProperty(person, "age"); // 类型为 number // getProperty(person, "height"); // 编译错误:height 不是 person 的属性 -
组合 多个约束条件,例如要求类型同时满足两个接口:
interface A { a: number; } interface B { b: string; } function combine<T extends A & B>(obj: T): void { console.log(obj.a, obj.b); // 可安全访问 a 和 b }
泛型默认类型与实用技巧
你可以为泛型参数设置默认类型,简化常见场景的使用。
-
设置 默认类型,在
<T = DefaultType>中指定:function createArray<T = string>(length: number, value: T): T[] { return Array(length).fill(value); } -
调用 时省略类型参数,自动使用默认值:
const strArr = createArray(3, "x"); // 类型为 string[] const numArr = createArray<number>(3, 1); // 显式覆盖默认类型,得到 number[] -
在类中使用 泛型,默认类型让实例化更简洁:
class Queue<T = number> { private items: T[] = []; enqueue(item: T) { this.items.push(item); } dequeue(): T | undefined { return this.items.shift(); } } const numQueue = new Queue(); // T 默认为 number const strQueue = new Queue<string>(); // 显式指定 T 为 string
避免常见错误
-
不要 在泛型函数内部假设类型的具体结构:
// 错误示例:未加约束就访问属性 function badExample<T>(arg: formulate T): void { console.log(arg.toString()); // 危险!虽然大多数类型有 toString,但不保证 }正确做法是添加约束,或使用类型守卫。
-
不要 混淆类型参数和值参数:
// 错误:试图把类型当作运行时值使用 function wrong<T>(): void { console.log(T); // 编译错误!T 只存在于编译期 } -
谨慎使用
any绕过泛型约束——这会破坏类型安全,失去泛型的意义。
// 不推荐:用 any 代替约束
function unsafe<T>(arg: any): T {
return arg as T;
}
正确方式应通过合理约束确保类型安全。

暂无评论,快来抢沙发吧!