05 TypeScript 类、泛型的使用实践记录 | 豆包MarsCode AI刷题

51 阅读2分钟

实践目标

  1. 聚焦于 TypeScript 中的 泛型 的使用,
  2. 理解 TypeScript 中泛型的基本概念。
  3. 学习如何结合类使用泛型。
  4. 通过实际案例演示泛型在增加代码灵活性和安全性方面的作用。
  5. 使用类型约束(extends)对泛型进行限制。

项目内容

选题方向

设计一个小型项目,例如 "通用数据存储类""自定义列表操作类" 。通过实现:

  • 一个支持多种数据类型的存储类。
  • 泛型约束确保数据类型一致性和安全性。
  • 代码示例展示灵活性和实际场景应用。

项目实现

1. 创建一个泛型类

实现一个 Storage<T> 类,用于存储任意类型的数据。


class DataStorage<T> {
  private items: T[] = [];

  addItem(item: T): void {
    this.items.push(item);
  }

  getAllItems(): T[] {
    return this.items;
  }

  removeItem(index: number): void {
    if (index >= 0 && index < this.items.length) {
      this.items.splice(index, 1);
    } else {
      console.error('Invalid index');
    }
  }
}

// 示例
const stringStorage = new DataStorage<string>();
stringStorage.addItem('Hello');
console.log(stringStorage.getAllItems()); // 输出: ['Hello']

运行结果

image.png


2. 使用泛型类

展示如何使用 Storage<T> 类存储不同类型的数据。

// 存储字符串
const stringStorage = new Storage<string>();
stringStorage.addItem('Hello');
stringStorage.addItem('World');
console.log(stringStorage.getAllItems()); // 输出: ['Hello', 'World']

// 存储数字
const numberStorage = new Storage<number>();
numberStorage.addItem(42);
numberStorage.addItem(99);
console.log(numberStorage.getAllItems()); // 输出: [42, 99]

// 存储对象
type User = { id: number; name: string };
const userStorage = new Storage<User>();
userStorage.addItem({ id: 1, name: 'Alice' });
userStorage.addItem({ id: 2, name: 'Bob' });
console.log(userStorage.getAllItems());
// 输出: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]

运行结果

image.png


3. 添加类型约束

通过 extends 对泛型参数添加约束,确保类型符合预期。例如,限制泛型类型必须是具有 id 属性的对象。

interface HasId {
  id: number;
}

class IdStorage<T extends HasId> {
  private items: T[] = [];

  addItem(item: T): void {
    this.items.push(item);
  }

  getItemById(id: number): T | undefined {
    return this.items.find(item => item.id === id);
  }

  getAllItems(): T[] {
    return this.items;
  }
}

// 使用带约束的泛型类
const idStorage = new IdStorage<{ id: number; name: string }>();
idStorage.addItem({ id: 1, name: 'Alice' });
idStorage.addItem({ id: 2, name: 'Bob' });

console.log(idStorage.getItemById(1)); // 输出: { id: 1, name: 'Alice' }
console.log(idStorage.getAllItems());
// 输出: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]

运行结果

image.png


4. 综合案例:缓存系统

创建一个缓存系统类,存储带有过期时间的数据。

interface CacheItem<T> {
  data: T;
  expiry: Date;
}

class Cache<T> {
  private cache: Map<string, CacheItem<T>> = new Map();

  set(key: string, data: T, ttl: number): void {
    const expiry = new Date(Date.now() + ttl);
    this.cache.set(key, { data, expiry });
  }

  get(key: string): T | undefined {
    const item = this.cache.get(key);
    if (!item) return undefined;

    if (item.expiry > new Date()) {
      return item.data;
    } else {
      this.cache.delete(key); // 删除过期缓存
      return undefined;
    }
  }

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

// 使用缓存系统
const cache = new Cache<number>();
cache.set('pi', 3.14159, 5000); // 缓存 5 秒
console.log(cache.get('pi')); // 输出: 3.14159
setTimeout(() => console.log(cache.get('pi')), 6000); // 输出: undefined (过期)

运行结果

image.png


总结

  1. 灵活性:通过泛型,Storage<T> 类可以存储任何类型的数据,而无需为每种类型单独创建类。
  2. 安全性:使用类型约束(如 T extends HasId),保证了类型的准确性。
  3. 扩展性:可以轻松地为泛型类添加新方法,如 Cache<T> 中的过期处理逻辑。
  4. 实际应用场景:泛型在存储系统、工具类(如队列、栈)、缓存系统等场景中尤为常见。

工具

-typescript在线

参考