TypeScript 泛型深度解析
目录
泛型概述
什么是泛型?
泛型(Generics)是 TypeScript 中最强大的特性之一,它允许我们创建可重用的组件,这些组件可以支持多种类型,而不是单一类型。泛型提供了一种方式来创建可重用的代码,同时保持类型安全。
为什么需要泛型?
// 没有泛型的问题
function identityString(arg: string): string {
return arg;
}
function identityNumber(arg: number): number {
return arg;
}
function identityBoolean(arg: boolean): boolean {
return arg;
}
// 使用 any 的问题
function identityAny(arg: any): any {
return arg; // 失去了类型信息
}
// 泛型解决方案
function identity<T>(arg: T): T {
return arg; // 保持类型信息,同时支持多种类型
}
泛型的基本语法
// 基本泛型函数
function genericFunction<T>(arg: T): T {
return arg;
}
// 多个类型参数
function pair<T, U>(first: T, second: U): [T, U] {
return [first, second];
}
// 使用泛型
let result1 = genericFunction<string>("hello"); // 显式指定类型
let result2 = genericFunction("hello"); // 类型推断
let result3 = pair<string, number>("hello", 42); // 多个类型参数
泛型函数
1. 基础泛型函数
// 简单的泛型函数
function firstElement<T>(arr: T[]): T | undefined {
return arr[0];
}
// 使用示例
let numbers = [1, 2, 3, 4, 5];
let firstNumber = firstElement(numbers); // number | undefined
let strings = ["hello", "world"];
let firstString = firstElement(strings); // string | undefined
// 显式指定类型
let firstAny = firstElement<any>([1, "hello", true]); // any | undefined
2. 多参数泛型函数
// 两个类型参数
function map<T, U>(array: T[], transform: (item: T) => U): U[] {
return array.map(transform);
}
// 使用示例
let numbers = [1, 2, 3, 4, 5];
let strings = map(numbers, n => n.toString()); // string[]
let doubled = map(numbers, n => n * 2); // number[]
// 三个类型参数
function reduce<T, U, V>(
array: T[],
transform: (item: T) => U,
reducer: (acc: V, current: U) => V,
initial: V
): V {
return array.map(transform).reduce(reducer, initial);
}
3. 泛型函数的重载
// 泛型函数重载
function process<T>(value: T): T;
function process<T>(value: T[]): T[];
function process<T>(value: T | T[]): T | T[] {
if (Array.isArray(value)) {
return value.map(item => item); // 处理数组
} else {
return value; // 处理单个值
}
}
// 使用
let singleValue = process("hello"); // string
let arrayValue = process(["a", "b", "c"]); // string[]
4. 异步泛型函数
// 异步泛型函数
async function fetchData<T>(url: string): Promise<T> {
const response = await fetch(url);
return response.json() as T;
}
// 使用示例
interface User {
id: number;
name: string;
email: string;
}
async function getUser(id: number): Promise<User> {
return fetchData<User>(`/api/users/${id}`);
}
async function getUsers(): Promise<User[]> {
return fetchData<User[]>('/api/users');
}
泛型接口
1. 基础泛型接口
// 简单的泛型接口
interface Container<T> {
value: T;
getValue(): T;
setValue(value: T): void;
}
// 实现泛型接口
class StringContainer implements Container<string> {
constructor(public value: string) {}
getValue(): string {
return this.value;
}
setValue(value: string): void {
this.value = value;
}
}
class NumberContainer implements Container<number> {
constructor(public value: number) {}
getValue(): number {
return this.value;
}
setValue(value: number): void {
this.value = value;
}
}
2. 函数类型的泛型接口
// 泛型函数接口
interface Transformer<T, U> {
(input: T): U;
}
// 使用泛型函数接口
let stringToNumber: Transformer<string, number> = (str) => parseInt(str);
let numberToString: Transformer<number, string> = (num) => num.toString();
let booleanToString: Transformer<boolean, string> = (bool) => bool ? "true" : "false";
// 更复杂的函数接口
interface Comparator<T> {
(a: T, b: T): number;
}
interface Sorter<T> {
sort(array: T[], comparator?: Comparator<T>): T[];
}
class ArraySorter<T> implements Sorter<T> {
sort(array: T[], comparator?: Comparator<T>): T[] {
if (comparator) {
return [...array].sort(comparator);
}
return [...array].sort();
}
}
3. 索引签名的泛型接口
// 泛型字典接口
interface Dictionary<T> {
[key: string]: T;
}
// 使用示例
let stringDict: Dictionary<string> = {
"name": "张三",
"city": "北京"
};
let numberDict: Dictionary<number> = {
"age": 30,
"score": 95
};
// 更复杂的索引签名
interface Cache<T> {
[key: string]: T;
get(key: string): T | undefined;
set(key: string, value: T): void;
has(key: string): boolean;
delete(key: string): boolean;
}
class MemoryCache<T> implements Cache<T> {
[key: string]: any;
private data: { [key: string]: T } = {};
get(key: string): T | undefined {
return this.data[key];
}
set(key: string, value: T): void {
this.data[key] = value;
}
has(key: string): boolean {
return key in this.data;
}
delete(key: string): boolean {
if (this.has(key)) {
delete this.data[key];
return true;
}
return false;
}
}
4. API 响应的泛型接口
// API 响应泛型接口
interface ApiResponse<T> {
success: boolean;
data: T;
message: string;
timestamp: Date;
meta?: {
total?: number;
page?: number;
limit?: number;
};
}
// 分页响应接口
interface PaginatedResponse<T> extends ApiResponse<T[]> {
meta: {
total: number;
page: number;
limit: number;
totalPages: number;
};
}
// 使用示例
interface User {
id: number;
name: string;
email: string;
}
// 单个用户响应
let userResponse: ApiResponse<User> = {
success: true,
data: { id: 1, name: "张三", email: "zhangsan@example.com" },
message: "获取用户成功",
timestamp: new Date()
};
// 用户列表响应
let usersResponse: PaginatedResponse<User> = {
success: true,
data: [
{ id: 1, name: "张三", email: "zhangsan@example.com" },
{ id: 2, name: "李四", email: "lisi@example.com" }
],
message: "获取用户列表成功",
timestamp: new Date(),
meta: {
total: 100,
page: 1,
limit: 10,
totalPages: 10
}
};
泛型类
1. 基础泛型类
// 简单的泛型类
class Stack<T> {
private items: T[] = [];
push(item: T): void {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
peek(): T | undefined {
return this.items[this.items.length - 1];
}
isEmpty(): boolean {
return this.items.length === 0;
}
size(): number {
return this.items.length;
}
toArray(): T[] {
return [...this.items];
}
}
// 使用泛型类
let numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);
let stringStack = new Stack<string>();
stringStack.push("hello");
stringStack.push("world");
2. 泛型类的继承
// 基础泛型类
class Collection<T> {
protected items: T[] = [];
add(item: T): void {
this.items.push(item);
}
get(index: number): T | undefined {
return this.items[index];
}
size(): number {
return this.items.length;
}
}
// 继承泛型类
class SortedCollection<T> extends Collection<T> {
private compareFn?: (a: T, b: T) => number;
constructor(compareFn?: (a: T, b: T) => number) {
super();
this.compareFn = compareFn;
}
add(item: T): void {
super.add(item);
this.sort();
}
private sort(): void {
if (this.compareFn) {
this.items.sort(this.compareFn);
} else {
this.items.sort();
}
}
}
// 使用
let sortedNumbers = new SortedCollection<number>((a, b) => a - b);
sortedNumbers.add(3);
sortedNumbers.add(1);
sortedNumbers.add(2);
// 内部自动排序为 [1, 2, 3]
3. 静态成员和泛型
// 泛型类的静态成员
class Utility<T> {
// 静态成员不能使用类的类型参数
static createArray<U>(length: number, value: U): U[] {
return new Array(length).fill(value);
}
// 实例成员可以使用类的类型参数
process(item: T): T {
return item;
}
}
// 使用静态方法
let stringArray = Utility.createArray(3, "hello"); // ["hello", "hello", "hello"]
let numberArray = Utility.createArray(5, 0); // [0, 0, 0, 0, 0]
4. 复杂的泛型类示例
// 事件发射器泛型类
type EventMap = Record<string, any>;
class EventEmitter<T extends EventMap> {
private listeners: {
[K in keyof T]?: Array<(data: T[K]) => void>;
} = {};
on<K extends keyof T>(event: K, listener: (data: T[K]) => void): void {
if (!this.listeners[event]) {
this.listeners[event] = [];
}
this.listeners[event]!.push(listener);
}
emit<K extends keyof T>(event: K, data: T[K]): void {
const eventListeners = this.listeners[event];
if (eventListeners) {
eventListeners.forEach(listener => listener(data));
}
}
off<K extends keyof T>(event: K, listener: (data: T[K]) => void): void {
const eventListeners = this.listeners[event];
if (eventListeners) {
const index = eventListeners.indexOf(listener);
if (index > -1) {
eventListeners.splice(index, 1);
}
}
}
}
// 定义事件类型
interface AppEvents {
userLogin: { userId: number; username: string };
userLogout: { userId: number };
dataUpdate: { table: string; id: number };
}
// 使用类型安全的事件发射器
const appEmitter = new EventEmitter<AppEvents>();
appEmitter.on('userLogin', (data) => {
// data 的类型是 { userId: number; username: string }
console.log(`User ${data.username} logged in`);
});
appEmitter.emit('userLogin', { userId: 1, username: '张三' });
泛型约束
1. 基础泛型约束
// 约束泛型必须有 length 属性
interface Lengthwise {
length: number;
}
function logLength<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 现在可以访问 length 属性
return arg;
}
// 使用
logLength("hello"); // ✅ 字符串有 length
logLength([1, 2, 3]); // ✅ 数组有 length
logLength({ length: 10 }); // ✅ 对象有 length
// logLength(123); // ❌ 数字没有 length
2. 使用类型参数约束
// 使用 keyof 约束
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
let person = { name: "张三", age: 30, city: "北京" };
let name = getProperty(person, "name"); // string
let age = getProperty(person, "age"); // number
// let invalid = getProperty(person, "salary"); // ❌ 'salary' 不存在于 person 中
// 更复杂的约束
function updateProperty<T, K extends keyof T>(
obj: T,
key: K,
value: T[K]
): T {
return { ...obj, [key]: value };
}
let updatedPerson = updateProperty(person, "age", 31); // 类型安全的更新
3. 条件约束
// 条件约束
type NonNullable<T> = T extends null | undefined ? never : T;
function processValue<T>(value: NonNullable<T>): T {
// value 不会是 null 或 undefined
return value as T;
}
// 约束为特定类型的子类型
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
interface Cat extends Animal {
meow(): void;
}
function petName<T extends Animal>(pet: T): string {
return pet.name; // 可以安全访问 name 属性
}
let dog: Dog = { name: "Buddy", breed: "Golden Retriever" };
let cat: Cat = { name: "Whiskers", meow: () => console.log("Meow!") };
console.log(petName(dog)); // "Buddy"
console.log(petName(cat)); // "Whiskers"
4. 多重约束
// 多重约束
interface Serializable {
serialize(): string;
}
interface Timestamped {
timestamp: Date;
}
function processData<T extends Serializable & Timestamped>(data: T): string {
return `${data.timestamp.toISOString()}: ${data.serialize()}`;
}
// 实现多重约束的类
class LogEntry implements Serializable, Timestamped {
constructor(
public message: string,
public timestamp: Date = new Date()
) {}
serialize(): string {
return JSON.stringify({
message: this.message,
timestamp: this.timestamp.toISOString()
});
}
}
let entry = new LogEntry("System started");
console.log(processData(entry));
5. 构造函数约束
// 约束为构造函数类型
interface Constructable {
new (...args: any[]): any;
}
function createInstance<T extends Constructable>(
constructor: T,
...args: any[]
): InstanceType<T> {
return new constructor(...args);
}
class User {
constructor(public name: string, public age: number) {}
}
class Product {
constructor(public name: string, public price: number) {}
}
// 使用
let user = createInstance(User, "张三", 30); // User 实例
let product = createInstance(Product, "手机", 999); // Product 实例
// 更具体的构造函数约束
interface UserConstructor {
new (name: string, age: number): User;
}
function createUser<T extends UserConstructor>(
UserClass: T,
name: string,
age: number
): InstanceType<T> {
return new UserClass(name, age);
}
高级泛型模式
1. 条件类型
// 基础条件类型
type IsString<T> = T extends string ? true : false;
type Test1 = IsString<string>; // true
type Test2 = IsString<number>; // false
// 更复杂的条件类型
type ApiResponse<T> = T extends string
? { message: T }
: T extends number
? { code: T }
: { data: T };
type StringResponse = ApiResponse<string>; // { message: string }
type NumberResponse = ApiResponse<number>; // { code: number }
type ObjectResponse = ApiResponse<object>; // { data: object }
// 分布式条件类型
type ToArray<T> = T extends any ? T[] : never;
type StringOrNumberArray = ToArray<string | number>; // string[] | number[]
2. infer 关键字
// 推断返回类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function getString(): string { return "hello"; }
function getNumber(): number { return 42; }
type StringReturn = ReturnType<typeof getString>; // string
type NumberReturn = ReturnType<typeof getNumber>; // number
// 推断参数类型
type Parameters<T> = T extends (...args: infer P) => any ? P : never;
function add(a: number, b: number): number { return a + b; }
type AddParams = Parameters<typeof add>; // [number, number]
// 推断数组元素类型
type ArrayElement<T> = T extends (infer U)[] ? U : never;
type StringElement = ArrayElement<string[]>; // string
type NumberElement = ArrayElement<number[]>; // number
// 推断 Promise 的值类型
type Awaited<T> = T extends Promise<infer U> ? U : T;
type PromiseString = Awaited<Promise<string>>; // string
type DirectString = Awaited<string>; // string
3. 递归类型
// 深度只读类型
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};
interface User {
name: string;
profile: {
age: number;
address: {
street: string;
city: string;
};
};
}
type ReadonlyUser = DeepReadonly<User>;
// 所有属性都变成只读,包括嵌套对象
// 深度可选类型
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
type PartialUser = DeepPartial<User>;
// 所有属性都变成可选,包括嵌套对象
// 路径类型
type Path<T> = T extends object
? {
[K in keyof T]: K extends string
? T[K] extends object
? `${K}` | `${K}.${Path<T[K]>}`
: `${K}`
: never
}[keyof T]
: never;
type UserPaths = Path<User>;
// "name" | "profile" | "profile.age" | "profile.address" | "profile.address.street" | "profile.address.city"
4. 模板字面量类型
// 基础模板字面量类型
type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<"click">; // "onClick"
type HoverEvent = EventName<"hover">; // "onHover"
// 组合模板字面量类型
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
type ApiPath = "users" | "products" | "orders";
type ApiEndpoint = `${HttpMethod} /api/${ApiPath}`;
// 结果类型:
// "GET /api/users" | "POST /api/users" | "PUT /api/users" | "DELETE /api/users" |
// "GET /api/products" | "POST /api/products" | "PUT /api/products" | "DELETE /api/products" |
// "GET /api/orders" | "POST /api/orders" | "PUT /api/orders" | "DELETE /api/orders"
// 解析模板字面量类型
type ParseApiEndpoint<T extends string> =
T extends `${infer Method} /api/${infer Path}`
? { method: Method; path: Path }
: never;
type ParsedEndpoint = ParseApiEndpoint<"GET /api/users">;
// { method: "GET"; path: "users" }
// CSS 属性类型
type CSSProperty =
| "color"
| "background-color"
| "font-size"
| "margin"
| "padding";
type CSSVariableName<T extends CSSProperty> = `--${T}`;
type ColorVariable = CSSVariableName<"color">; // "--color"
映射类型
1. 基础映射类型
// 基础映射类型语法
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
type Partial<T> = {
[P in keyof T]?: T[P];
};
type Required<T> = {
[P in keyof T]-?: T[P];
};
// 使用示例
interface User {
name: string;
age?: number;
email: string;
}
type ReadonlyUser = Readonly<User>;
// { readonly name: string; readonly age?: number; readonly email: string; }
type PartialUser = Partial<User>;
// { name?: string; age?: number; email?: string; }
type RequiredUser = Required<User>;
// { name: string; age: number; email: string; }
2. 键映射
// 键名转换
type Getters<T> = {
[P in keyof T as `get${Capitalize<string & P>}`]: () => T[P];
};
type Setters<T> = {
[P in keyof T as `set${Capitalize<string & P>}`]: (value: T[P]) => void;
};
interface Person {
name: string;
age: number;
}
type PersonGetters = Getters<Person>;
// { getName: () => string; getAge: () => number; }
type PersonSetters = Setters<Person>;
// { setName: (value: string) => void; setAge: (value: number) => void; }
// 过滤键
type PickByType<T, U> = {
[P in keyof T as T[P] extends U ? P : never]: T[P];
};
interface Mixed {
name: string;
age: number;
isActive: boolean;
tags: string[];
}
type StringProperties = PickByType<Mixed, string>;
// { name: string; }
type NumberProperties = PickByType<Mixed, number>;
// { age: number; }
3. 条件映射
// 条件映射类型
type NullableProperties<T> = {
[P in keyof T]: T[P] | null;
};
type OptionalNullable<T> = {
[P in keyof T]?: T[P] | null;
};
interface User {
id: number;
name: string;
email: string;
}
type NullableUser = NullableProperties<User>;
// { id: number | null; name: string | null; email: string | null; }
// 基于条件的属性转换
type StringifyProperties<T> = {
[P in keyof T]: T[P] extends string ? T[P] : string;
};
interface Data {
name: string;
age: number;
isActive: boolean;
}
type StringifiedData = StringifyProperties<Data>;
// { name: string; age: string; isActive: string; }
4. 递归映射类型
// 深度映射
type DeepNullable<T> = {
[P in keyof T]: T[P] extends object ? DeepNullable<T[P]> : T[P] | null;
};
interface NestedData {
user: {
profile: {
name: string;
age: number;
};
settings: {
theme: string;
notifications: boolean;
};
};
metadata: {
version: string;
};
}
type DeepNullableData = DeepNullable<NestedData>;
// 所有嵌套属性都变成可为 null
// 深度转换类型
type DeepStringify<T> = {
[P in keyof T]: T[P] extends object
? DeepStringify<T[P]>
: string;
};
type StringifiedNestedData = DeepStringify<NestedData>;
// 所有最终属性都变成 string 类型
实用工具类型
1. TypeScript 内置工具类型
// Partial<T> - 使所有属性可选
interface User {
id: number;
name: string;
email: string;
age: number;
}
type PartialUser = Partial<User>;
// { id?: number; name?: string; email?: string; age?: number; }
function updateUser(user: User, updates: Partial<User>): User {
return { ...user, ...updates };
}
// Required<T> - 使所有属性必需
interface Config {
apiUrl?: string;
timeout?: number;
retries?: number;
}
type RequiredConfig = Required<Config>;
// { apiUrl: string; timeout: number; retries: number; }
// Readonly<T> - 使所有属性只读
type ReadonlyUser = Readonly<User>;
// { readonly id: number; readonly name: string; readonly email: string; readonly age: number; }
// Pick<T, K> - 选择特定属性
type UserSummary = Pick<User, 'id' | 'name'>;
// { id: number; name: string; }
// Omit<T, K> - 排除特定属性
type UserWithoutId = Omit<User, 'id'>;
// { name: string; email: string; age: number; }
// Record<K, T> - 创建键值对类型
type UserRoles = Record<string, string[]>;
// { [key: string]: string[]; }
let roles: UserRoles = {
"admin": ["read", "write", "delete"],
"user": ["read"],
"guest": []
};
2. 函数相关工具类型
// ReturnType<T> - 获取函数返回类型
function getUser(): User {
return { id: 1, name: "张三", email: "zhangsan@example.com", age: 30 };
}
type GetUserReturn = ReturnType<typeof getUser>; // User
// Parameters<T> - 获取函数参数类型
function createUser(name: string, age: number, email: string): User {
return { id: Date.now(), name, age, email };
}
type CreateUserParams = Parameters<typeof createUser>; // [string, number, string]
// ConstructorParameters<T> - 获取构造函数参数类型
class UserService {
constructor(private apiUrl: string, private timeout: number) {}
}
type UserServiceParams = ConstructorParameters<typeof UserService>; // [string, number]
// InstanceType<T> - 获取构造函数实例类型
type UserServiceInstance = InstanceType<typeof UserService>; // UserService
3. 字符串操作工具类型
// Uppercase<T> - 转大写
type UppercaseHello = Uppercase<"hello">; // "HELLO"
// Lowercase<T> - 转小写
type LowercaseHELLO = Lowercase<"HELLO">; // "hello"
// Capitalize<T> - 首字母大写
type CapitalizeHello = Capitalize<"hello">; // "Hello"
// Uncapitalize<T> - 首字母小写
type UncapitalizeHello = Uncapitalize<"Hello">; // "hello"
// 实际应用
type HttpMethod = "get" | "post" | "put" | "delete";
type UppercaseMethod = Uppercase<HttpMethod>; // "GET" | "POST" | "PUT" | "DELETE"
type EventName<T extends string> = `on${Capitalize<T>}`;
type Events = EventName<"click" | "hover" | "focus">; // "onClick" | "onHover" | "onFocus"
4. 自定义工具类型
// NonNullable<T> - 排除 null 和 undefined
type NonNullable<T> = T extends null | undefined ? never : T;
type NonNullableString = NonNullable<string | null | undefined>; // string
// Exclude<T, U> - 从 T 中排除 U
type Exclude<T, U> = T extends U ? never : T;
type WithoutString = Exclude<string | number | boolean, string>; // number | boolean
// Extract<T, U> - 从 T 中提取 U
type Extract<T, U> = T extends U ? T : never;
type OnlyString = Extract<string | number | boolean, string>; // string
// 自定义工具类型
type DeepRequired<T> = {
[P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P];
};
type ValueOf<T> = T[keyof T];
interface Colors {
red: "#ff0000";
green: "#00ff00";
blue: "#0000ff";
}
type ColorValue = ValueOf<Colors>; // "#ff0000" | "#00ff00" | "#0000ff"
// 函数重载工具类型
type Overload<T> = T extends {
(...args: infer A1): infer R1;
(...args: infer A2): infer R2;
(...args: infer A3): infer R3;
} ? [
(...args: A1) => R1,
(...args: A2) => R2,
(...args: A3) => R3
] : T extends {
(...args: infer A1): infer R1;
(...args: infer A2): infer R2;
} ? [
(...args: A1) => R1,
(...args: A2) => R2
] : T extends (...args: infer A) => infer R ? [(...args: A) => R] : never;
实战案例
1. 类型安全的状态管理
// 状态管理系统
interface State {
user: {
id: number;
name: string;
email: string;
} | null;
posts: Array<{
id: number;
title: string;
content: string;
authorId: number;
}>;
loading: {
user: boolean;
posts: boolean;
};
}
// 动作类型
type Action<T extends keyof State> = {
type: `SET_${Uppercase<string & T>}`;
payload: State[T];
} | {
type: `UPDATE_${Uppercase<string & T>}`;
payload: Partial<State[T]>;
};
// 生成所有可能的动作
type UserAction = Action<'user'>;
type PostsAction = Action<'posts'>;
type LoadingAction = Action<'loading'>;
type AllActions = UserAction | PostsAction | LoadingAction;
// 状态管理器
class StateManager<T extends Record<string, any>> {
private state: T;
private listeners: Array<(state: T) => void> = [];
constructor(initialState: T) {
this.state = initialState;
}
getState(): T {
return { ...this.state };
}
setState<K extends keyof T>(key: K, value: T[K]): void {
this.state = { ...this.state, [key]: value };
this.notifyListeners();
}
updateState<K extends keyof T>(key: K, updates: Partial<T[K]>): void {
this.state = {
...this.state,
[key]: { ...this.state[key], ...updates }
};
this.notifyListeners();
}
subscribe(listener: (state: T) => void): () => void {
this.listeners.push(listener);
return () => {
const index = this.listeners.indexOf(listener);
if (index > -1) {
this.listeners.splice(index, 1);
}
};
}
private notifyListeners(): void {
this.listeners.forEach(listener => listener(this.state));
}
}
// 使用
const stateManager = new StateManager<State>({
user: null,
posts: [],
loading: { user: false, posts: false }
});
// 类型安全的状态更新
stateManager.setState('user', { id: 1, name: '张三', email: 'zhangsan@example.com' });
stateManager.updateState('loading', { user: true });
2. 类型安全的 API 客户端
// API 端点定义
interface ApiEndpoints {
'GET /users': {
params: { page?: number; limit?: number };
response: { users: User[]; total: number };
};
'GET /users/:id': {
params: { id: number };
response: User;
};
'POST /users': {
body: Omit<User, 'id'>;
response: User;
};
'PUT /users/:id': {
params: { id: number };
body: Partial<Omit<User, 'id'>>;
response: User;
};
'DELETE /users/:id': {
params: { id: number };
response: { success: boolean };
};
}
// 提取路径参数
type ExtractParams<T extends string> =
T extends `${infer _Start}:${infer Param}/${infer Rest}`
? { [K in Param]: string | number } & ExtractParams<`/${Rest}`>
: T extends `${infer _Start}:${infer Param}`
? { [K in Param]: string | number }
: {};
// API 客户端
class ApiClient {
constructor(private baseUrl: string) {}
async request<T extends keyof ApiEndpoints>(
endpoint: T,
options: ApiEndpoints[T] extends { params: infer P }
? ApiEndpoints[T] extends { body: infer B }
? { params: P; body: B }
: { params: P }
: ApiEndpoints[T] extends { body: infer B }
? { body: B }
: {}
): Promise<ApiEndpoints[T]['response']> {
// 实现 API 调用逻辑
const [method, path] = (endpoint as string).split(' ');
// 构建 URL
let url = this.baseUrl + path;
if ('params' in options) {
// 替换路径参数
Object.entries(options.params as Record<string, any>).forEach(([key, value]) => {
url = url.replace(`:${key}`, String(value));
});
}
// 发送请求
const response = await fetch(url, {
method,
headers: {
'Content-Type': 'application/json',
},
body: 'body' in options ? JSON.stringify(options.body) : undefined,
});
return response.json();
}
}
// 使用示例
const apiClient = new ApiClient('https://api.example.com');
// 类型安全的 API 调用
async function example() {
// GET 请求
const users = await apiClient.request('GET /users', {
params: { page: 1, limit: 10 }
});
// GET 单个用户
const user = await apiClient.request('GET /users/:id', {
params: { id: 1 }
});
// POST 创建用户
const newUser = await apiClient.request('POST /users', {
body: { name: '张三', email: 'zhangsan@example.com', age: 30 }
});
// PUT 更新用户
const updatedUser = await apiClient.request('PUT /users/:id', {
params: { id: 1 },
body: { name: '李四' }
});
// DELETE 删除用户
const deleteResult = await apiClient.request('DELETE /users/:id', {
params: { id: 1 }
});
}
3. 类型安全的表单验证
// 验证规则类型
type ValidationRule<T> = {
required?: boolean;
minLength?: number;
maxLength?: number;
pattern?: RegExp;
custom?: (value: T) => string | null;
};
type ValidationRules<T> = {
[K in keyof T]?: ValidationRule<T[K]>;
};
type ValidationErrors<T> = {
[K in keyof T]?: string;
};
// 表单验证器
class FormValidator<T extends Record<string, any>> {
private rules: ValidationRules<T>;
constructor(rules: ValidationRules<T>) {
this.rules = rules;
}
validate(data: T): ValidationErrors<T> {
const errors: ValidationErrors<T> = {};
for (const key in this.rules) {
const rule = this.rules[key];
const value = data[key];
if (rule) {
const error = this.validateField(key, value, rule);
if (error) {
errors[key] = error;
}
}
}
return errors;
}
private validateField<K extends keyof T>(
key: K,
value: T[K],
rule: ValidationRule<T[K]>
): string | null {
if (rule.required && (value === undefined || value === null || value === '')) {
return `${String(key)} 是必填项`;
}
if (typeof value === 'string') {
if (rule.minLength && value.length < rule.minLength) {
return `${String(key)} 最少需要 ${rule.minLength} 个字符`;
}
if (rule.maxLength && value.length > rule.maxLength) {
return `${String(key)} 最多只能有 ${rule.maxLength} 个字符`;
}
if (rule.pattern && !rule.pattern.test(value)) {
return `${String(key)} 格式不正确`;
}
}
if (rule.custom) {
return rule.custom(value);
}
return null;
}
isValid(data: T): boolean {
const errors = this.validate(data);
return Object.keys(errors).length === 0;
}
}
// 使用示例
interface UserForm {
username: string;
email: string;
password: string;
confirmPassword: string;
age: number;
}
const userFormValidator = new FormValidator<UserForm>({
username: {
required: true,
minLength: 3,
maxLength: 20,
pattern: /^[a-zA-Z0-9_]+$/
},
email: {
required: true,
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
},
password: {
required: true,
minLength: 8,
custom: (value) => {
if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(value)) {
return '密码必须包含大小写字母和数字';
}
return null;
}
},
confirmPassword: {
required: true,
custom: (value) => {
// 注意:这里需要访问其他字段,实际实现可能需要调整
return null;
}
},
age: {
required: true,
custom: (value) => {
if (value < 18 || value > 120) {
return '年龄必须在 18-120 之间';
}
return null;
}
}
});
// 验证表单
const formData: UserForm = {
username: 'john_doe',
email: 'john@example.com',
password: 'Password123',
confirmPassword: 'Password123',
age: 25
};
const errors = userFormValidator.validate(formData);
const isValid = userFormValidator.isValid(formData);
console.log('验证错误:', errors);
console.log('表单有效:', isValid);
总结
泛型是 TypeScript 中最强大和最重要的特性之一。通过本文的深入学习,您应该掌握了:
核心概念
- 泛型函数:创建可重用的类型安全函数
- 泛型接口:定义灵活的数据结构契约
- 泛型类:构建可重用的类型安全类
- 泛型约束:限制泛型参数的类型范围
高级特性
- 条件类型:基于条件的类型选择
- 映射类型:转换现有类型的结构
- 模板字面量类型:类型级别的字符串操作
- 递归类型:处理深层嵌套结构
实用工具
- 内置工具类型:Partial、Required、Pick、Omit 等
- 自定义工具类型:根据需求创建专用类型
- 类型推断:使用 infer 关键字进行类型推断
最佳实践
- 渐进式采用:从简单的泛型开始,逐步使用高级特性
- 类型约束:合理使用约束确保类型安全
- 可读性:保持类型定义的清晰和可理解
- 性能考虑:避免过度复杂的类型计算
掌握泛型将大大提升您的 TypeScript 编程能力,使您能够编写更加类型安全、可维护和可重用的代码。在实际项目中,建议从基础泛型开始应用,随着经验的积累逐步使用更高级的特性。