TypeScript泛型编程指南


TypeScript泛型编程指南

泛型是TypeScript中最强大也最令人困惑的特性之一。掌握泛型编程,可以编写出既类型安全又高度复用的代码。本文将从基础到进阶,系统讲解TypeScript泛型的使用方法和设计模式。

一、泛型基础

// 基本泛型函数
function identity<T>(arg: T): T {
  return arg;
}

// 泛型接口
interface Repository<T> {
  findById(id: string): Promise<T>;
  findAll(): Promise<T[]>;
  create(data: Omit<T, 'id'>): Promise<T>;
  update(id: string, data: Partial<T>): Promise<T>;
  delete(id: string): Promise<void>;
}

// 泛型类
class DataStore<T> {
  private items: T[] = [];
  add(item: T): void { this.items.push(item); }
  get(index: number): T | undefined { return this.items[index]; }
  getAll(): T[] { return [...this.items]; }
}

二、泛型约束

// extends约束
interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(arg: T): T {
  console.log(arg.length);
  return arg;
}

logLength("hello");     // OK
logLength([1, 2, 3]);   // OK
logLength(123);         // Error: number没有length

// keyof约束
function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

const user = { name: '张三', age: 25 };
getProperty(user, 'name');  // OK, 返回string
getProperty(user, 'age');   // OK, 返回number
getProperty(user, 'email'); // Error

三、条件类型与推断

// 条件类型
type IsString<T> = T extends string ? true : false;
type A = IsString<string>;  // true
type B = IsString<number>;  // false

// infer关键字 - 类型推断
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type Parameters<T> = T extends (...args: infer P) => any ? P : never;

// 实用:提取Promise内部类型
type Unpacked<T> = T extends Promise<infer U> ? U : T;
type Result = Unpacked<Promise<string>>;  // string

四、映射类型与工具类型

// 内置工具类型
type Partial<T> = { [K in keyof T]?: T[K] };       // 所有属性可选
type Required<T> = { [K in keyof T]-?: T[K] };     // 所有属性必需
type Readonly<T> = { readonly [K in keyof T]: T[K] }; // 所有属性只读
type Pick<T, K extends keyof T> = { [P in K]: T[P] }; // 选取部分属性
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>; // 排除属性

// 自定义映射类型
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
// 将指定属性变为可选
type UserWithOptionalEmail = Optional<User, 'email' | 'phone'>;

type DeepPartial<T> = {
  [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};

五、泛型设计模式

// 工厂模式
type Constructor<T> = new (...args: any[]) => T;
function createInstance<T>(ctor: Constructor<T>, ...args: any[]): T {
  return new ctor(...args);
}

// Builder模式
class QueryBuilder<T> {
  private conditions: string[] = [];
  where<K extends keyof T>(field: K, value: T[K]): this {
    this.conditions.push(`${String(field)} = ${value}`);
    return this;
  }
  build(): string { return this.conditions.join(' AND '); }
}

TypeScript泛型是一个强大的类型系统工具,掌握它可以极大地提升代码质量和开发体验。建议在实际项目中多练习,从简单的泛型函数开始,逐步过渡到复杂的条件类型和映射类型。


0.049757s