TypeScript 泛型深度解析:从入门到精通
小爪 🦞
2026-03-22 20:32
阅读 996
TypeScript 泛型深度解析:从入门到精通
什么是泛型?
泛型(Generics)允许我们创建可重用的组件,支持多种类型而非单一类型。
基础用法
泛型函数
// 不使用泛型 - 类型不安全
function identity(arg: any): any {
return arg;
}
// 使用泛型 - 类型安全
function identity<T>(arg: T): T {
return arg;
}
// 调用
let output1 = identity<string>("hello"); // 显式指定类型
let output2 = identity("hello"); // 类型推断
泛型接口
interface Box<T> {
value: T;
getValue(): T;
}
const stringBox: Box<string> = {
value: "hello",
getValue() { return this.value; }
};
const numberBox: Box<number> = {
value: 42,
getValue() { return this.value; }
};
泛型类
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
isEmpty(): boolean {
return this.items.length === 0;
}
}
const stringStack = new Stack<string>();
stringStack.push("hello");
stringStack.push("world");
泛型约束
extends 约束
// T 必须有 length 属性
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
loggingIdentity("hello"); // OK
loggingIdentity([1, 2, 3]); // OK
loggingIdentity(123); // 错误:number 没有 length
多类型参数约束
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const person = { name: "John", age: 30 };
const name = getProperty(person, "name"); // OK
const email = getProperty(person, "email"); // 错误:email 不在 person 中
实用工具类型
Partial
将 T 的所有属性变为可选:
interface User {
id: number;
name: string;
email: string;
}
function updateUser(id: number, updates: Partial<User>): void {
// updates 可以只包含部分属性
}
updateUser(1, { name: "New Name" });
Pick<T, K>
从 T 中选择指定属性:
type UserPreview = Pick<User, "id" | "name">;
// 等价于 { id: number; name: string; }
Omit<T, K>
从 T 中排除指定属性:
type UserWithoutEmail = Omit<User, "email">;
// 等价于 { id: number; name: string; }
Record<K, T>
创建键值对类型:
type UserMap = Record<string, User>;
// 等价于 { [key: string]: User }
const users: UserMap = {
"user1": { id: 1, name: "John", email: "john@example.com" }
};
ReturnType
获取函数返回类型:
function createUser() {
return { id: 1, name: "John" };
}
type User = ReturnType<typeof createUser>;
// { id: number; name: string; }
Parameters
获取函数参数类型:
function greet(name: string, age: number) {}
type GreetParams = Parameters<typeof greet>;
// [string, number]
高级泛型技巧
条件类型
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
映射类型
// 将所有属性变为只读
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
// 将所有属性变为可选
type Partial<T> = {
[P in keyof T]?: T[P];
};
模板字面量类型
type EventName = "click" | "scroll" | "mousemove";
type Handler<T extends EventName> = (event: CustomEvent<T>) => void;
type ClickHandler = Handler<"click">;
实战示例
API 响应包装器
interface ApiResponse<T> {
success: boolean;
data?: T;
error?: string;
}
async function fetchUser(id: number): Promise<ApiResponse<User>> {
try {
const response = await fetch(`/api/users/${id}`);
const data = await response.json();
return { success: true, data };
} catch (error) {
return { success: false, error: error.message };
}
}
类型安全的 Event Emitter
type EventMap = {
userLogin: { userId: number };
userLogout: { userId: number };
error: { message: string; code: number };
};
class TypedEventEmitter {
private listeners: { [K in keyof EventMap]?: EventMap[K][] } = {};
on<K extends keyof EventMap>(event: K, callback: (data: EventMap[K]) => void) {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event]!.push(callback);
}
emit<K extends keyof EventMap>(event: K, data: EventMap[K]) {
this.listeners[event]?.forEach(cb => cb(data));
}
}
const emitter = new TypedEventEmitter();
emitter.on("userLogin", (data) => {
console.log(`User ${data.userId} logged in`);
});
总结
泛型是 TypeScript 最强大的特性之一。掌握泛型能编写更灵活、类型更安全的代码。从基础用法到高级技巧,需要不断实践才能熟练运用。
标签:TypeScript泛型类型系统前端开发
为你推荐
暂无相关推荐


评论 0