Typescript泛型概念
TypeScript 的泛型(Generics)是一种创建可重用、类型安全代码的机制。简单说,就是"类型的变量"。
核心概念
泛型让你写代码时不指定具体类型,而是用一个"占位符",使用时再传入真正的类型。
// 不用泛型:只能处理 string
function getFirst(arr: string[]): string {
return arr[0];
}
// 使用泛型:可以处理任何类型
function getFirst<T>(arr: T[]): T {
return arr[0];
}
为什么需要泛型?
问题场景:
// 如果没有泛型,你需要为每种类型写一遍相同的逻辑
function getFirstString(arr: string[]): string {
return arr[0];
}
function getFirstNumber(arr: number[]): number {
return arr[0];
}
function getFirstUser(arr: User[]): User {
return arr[0];
}
// ... 无穷无尽
泛型解决方案:
// 一个函数搞定所有类型
function getFirst<T>(arr: T[]): T {
return arr[0];
}
// 使用时指定具体类型
const firstString = getFirst<string>(["a", "b", "c"]); // 返回 string
const firstNumber = getFirst<number>([1, 2, 3]); // 返回 number
const firstUser = getFirst<User>([user1, user2]); // 返回 User
泛型的几种用法
1. 函数泛型:
function identity<T>(value: T): T {
return value;
}
const result = identity<number>(42); // result 是 number 类型
2. 接口泛型:
interface Container<T> {
value: T;
getValue(): T;
}
const stringContainer: Container<string> = {
value: "hello",
getValue() {
return this.value;
},
};
3. 类泛型:
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
}
const numberStack = new Stack<number>();
numberStack.push(1); // ✅ 正确
numberStack.push("a"); // ❌ 类型错误
4. React 组件中的泛型:
// 一个通用的列表组件
interface ListProps<T> {
items: T[];
renderItem: (item: T) => React.ReactNode;
}
function List<T>({ items, renderItem }: ListProps<T>) {
return (
<ul>
{items.map((item, index) => (
<li key={index}>{renderItem(item)}</li>
))}
</ul>
);
}
// 使用
<List<User> items={users} renderItem={(user) => <span>{user.name}</span>} />;
泛型约束
有时你需要限制泛型的类型:
// T 必须有 length 属性
function logLength<T extends { length: number }>(arg: T): T {
console.log(arg.length); // 现在安全了,T 肯定有 length
return arg;
}
logLength("hello"); // ✅ string 有 length
logLength([1, 2, 3]); // ✅ array 有 length
logLength(123); // ❌ number 没有 length
类比理解
把泛型想象成:
- 函数的参数:
function add(a, b)中的a, b是值的占位符 - 泛型参数:
function identity<T>(value: T)中的T是类型的占位符
