Skip to content

TypeScript 泛型 Generic

泛型是 TypeScript 中非常重要的高级特性,它允许你创建可重用的组件,这些组件可以适用于多种类型而不是单一类型。本章节将详细介绍 TypeScript 泛型的使用。

什么是泛型?为什么要用?

什么是泛型?

泛型(Generics)是一种允许你在定义函数、接口或类时使用类型参数的特性。这些类型参数可以在使用时被具体的类型所替换。

为什么要用泛型?

  1. 代码复用:泛型允许你编写可重用的代码,适用于多种类型
  2. 类型安全:泛型可以在编译时提供类型检查,避免运行时错误
  3. 灵活性:泛型使代码更加灵活,可以适应不同的类型需求
  4. 可读性:泛型可以使代码更加清晰,明确表达代码的意图

泛型函数

基本泛型函数

示例:

typescript
// 泛型函数
function identity<T>(value: T): T {
  return value;
}

// 使用泛型函数
const numberValue = identity<number>(42); // 类型为 number
const stringValue = identity<string>("Hello"); // 类型为 string
const booleanValue = identity<boolean>(true); // 类型为 boolean

// 类型推断
const inferredValue = identity("TypeScript"); // 类型被推断为 string

多个类型参数

示例:

typescript
// 多个类型参数
function pair<T, U>(first: T, second: U): [T, U] {
  return [first, second];
}

// 使用
const numberAndString = pair<number, string>(42, "Hello"); // 类型为 [number, string]
const booleanAndNumber = pair<boolean, number>(true, 100); // 类型为 [boolean, number]

泛型接口

基本泛型接口

示例:

typescript
// 泛型接口
interface Container<T> {
  value: T;
  getValue(): T;
}

// 实现泛型接口
class NumberContainer implements Container<number> {
  value: number;
  constructor(value: number) {
    this.value = value;
  }
  getValue(): number {
    return this.value;
  }
}

class StringContainer implements Container<string> {
  value: string;
  constructor(value: string) {
    this.value = value;
  }
  getValue(): string {
    return this.value;
  }
}

// 使用
const numberContainer = new NumberContainer(42);
console.log(numberContainer.getValue()); // 42

const stringContainer = new StringContainer("Hello");
console.log(stringContainer.getValue()); // Hello

泛型函数接口

示例:

typescript
// 泛型函数接口
interface Mapper<T, U> {
  (value: T): U;
}

// 使用泛型函数接口
const numberToString: Mapper<number, string> = (value) => value.toString();
const stringToNumber: Mapper<string, number> = (value) => parseInt(value);

console.log(numberToString(42)); // "42"
console.log(stringToNumber("123")); // 123

泛型类

示例:

typescript
// 泛型类
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;
  }
}

// 使用
const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);
console.log(numberStack.pop()); // 3

const stringStack = new Stack<string>();
stringStack.push("a");
stringStack.push("b");
stringStack.push("c");
console.log(stringStack.pop()); // "c"

泛型约束

基本约束

示例:

typescript
// 定义一个有 length 属性的接口
interface Lengthwise {
  length: number;
}

// 泛型约束
function logLength<T extends Lengthwise>(value: T): void {
  console.log(`Length: ${value.length}`);
}

// 使用
logLength("Hello"); // Length: 5
logLength([1, 2, 3]); // Length: 3
logLength({ length: 10 }); // Length: 10

// 错误:number 类型没有 length 属性
// logLength(42); // 错误:Argument of type 'number' is not assignable to parameter of type 'Lengthwise'

多个约束

示例:

typescript
// 定义多个接口
interface Lengthwise {
  length: number;
}

interface HasName {
  name: string;
}

// 多个约束
function process<T extends Lengthwise & HasName>(value: T): void {
  console.log(`Name: ${value.name}, Length: ${value.length}`);
}

// 使用
process({ name: "Test", length: 10 }); // Name: Test, Length: 10

// 错误:缺少 name 属性
// process({ length: 10 }); // 错误:Argument of type '{ length: number; }' is not assignable to parameter of type 'Lengthwise & HasName'

// 错误:缺少 length 属性
// process({ name: "Test" }); // 错误:Argument of type '{ name: string; }' is not assignable to parameter of type 'Lengthwise & HasName'

默认泛型类型

示例:

typescript
// 默认泛型类型
function createArray<T = string>(length: number, value: T): T[] {
  return Array(length).fill(value);
}

// 使用
const stringArray = createArray(3, "Hello"); // 类型为 string[]
const numberArray = createArray<number>(3, 42); // 类型为 number[]
const booleanArray = createArray<boolean>(3, true); // 类型为 boolean[]

实战:封装通用工具函数

示例 1:通用缓存工具

typescript
// 泛型缓存接口
interface Cache<T> {
  set(key: string, value: T): void;
  get(key: string): T | undefined;
  remove(key: string): void;
  clear(): void;
}

// 实现泛型缓存类
class MemoryCache<T> implements Cache<T> {
  private cache: Map<string, T> = new Map();

  set(key: string, value: T): void {
    this.cache.set(key, value);
  }

  get(key: string): T | undefined {
    return this.cache.get(key);
  }

  remove(key: string): void {
    this.cache.delete(key);
  }

  clear(): void {
    this.cache.clear();
  }
}

// 使用
const userCache = new MemoryCache<{ id: number; name: string }>();
userCache.set("user1", { id: 1, name: "John" });
const user = userCache.get("user1");
console.log(user); // { id: 1, name: "John" }

const productCache = new MemoryCache<{ id: number; name: string; price: number }>();
productCache.set("product1", { id: 1, name: "Product 1", price: 99.99 });
const product = productCache.get("product1");
console.log(product); // { id: 1, name: "Product 1", price: 99.99 }

示例 2:通用 API 响应处理

typescript
// 泛型 API 响应接口
interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: {
    code: number;
    message: string;
  };
}

// 泛型 API 客户端
class ApiClient {
  async get<T>(url: string): Promise<ApiResponse<T>> {
    const response = await fetch(url);
    const data = await response.json();
    return data;
  }

  async post<T>(url: string, body: any): Promise<ApiResponse<T>> {
    const response = await fetch(url, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(body),
    });
    const data = await response.json();
    return data;
  }
}

// 定义数据类型
interface User {
  id: number;
  name: string;
  email: string;
}

interface Product {
  id: number;
  name: string;
  price: number;
}

// 使用
const apiClient = new ApiClient();

// 获取用户
async function fetchUser() {
  const response = await apiClient.get<User>("/api/users/1");
  if (response.success && response.data) {
    console.log(response.data.name);
  }
}

// 获取产品
async function fetchProduct() {
  const response = await apiClient.get<Product>("/api/products/1");
  if (response.success && response.data) {
    console.log(response.data.price);
  }
}

小结

本章节介绍了 TypeScript 泛型的使用,包括:

  • 什么是泛型?为什么要用?
  • 泛型函数
  • 泛型接口
  • 泛型类
  • 泛型约束
  • 默认泛型类型
  • 实战:封装通用工具函数

泛型是 TypeScript 中非常强大的特性,它可以帮助你创建可重用、类型安全的代码。通过使用泛型,你可以编写更加灵活、可维护的代码,特别是在处理不同类型数据的场景中。

在实际开发中,应该充分利用泛型来提高代码的复用性和类型安全性,特别是在开发通用工具、组件和库时。

© 2026 编程马·菜鸟教程 版权所有