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

44 阅读3分钟

一、TypeScript中类和泛型的基础概念

    • TypeScript 中的类是面向对象编程的核心工具,通过构造函数、属性、方法等定义对象的结构和行为,同时结合 publicprivateprotected 等访问修饰符控制成员的可见性。类支持继承、方法重写、静态成员、抽象类等高级特性,增强了代码的可复用性和扩展性。
  1. 泛型

    • 泛型在 TypeScript 中用于构建具有灵活性和类型安全性的代码。通过泛型,我们可以在定义函数、类或接口时使用类型参数(如 T),这些参数在调用时再由具体的类型实例化。这使得代码可以重用,同时避免丢失类型信息。
  2. 在类中使用泛型

    • 定义泛型类:泛型可以用于类的定义,使类能够适应多种类型场景,同时保持类型安全。通过在类名后添加类型参数(如 <T>),可以在类的属性和方法中使用该类型,支持灵活的类型传递。
    • 多泛型参数:泛型类可以接受多个类型参数。
    • 泛型与约束结合:结合类型约束限制参数范围,并支持继承和扩展,允许子类继续使用或固定父类的泛型。
    • 泛型类的继承:类可以继承另一个泛型类,并且可以为父类的泛型指定具体类型或保留泛型参数。

二、泛型的使用场景

  1. 通用数据结构

    • 创建一个支持多种数据类型的栈或队列。

    • 示例

      class Stack<T> {
          private elements: T[] = [];
          push(element: T): void {
              this.elements.push(element);
          }
          pop(): T | undefined {
              return this.elements.pop();
          }
      }
      
  2. 类型安全的工具函数

    • 使用泛型编写工具函数,如深拷贝函数或数据过滤函数。

    • 示例

      function filterArray<T>(array: T[], predicate: (value: T) => boolean): T[] {
          return array.filter(predicate);
      }
      
  3. API响应封装

    • 利用泛型封装后端接口的响应类型,确保前端处理数据的类型安全性。

    • 示例

      interface ApiResponse<T> {
          data: T;
          error?: string;
      }
      function fetchData<T>(url: string): Promise<ApiResponse<T>> {
          // 模拟异步请求
          return fetch(url)
              .then(res => res.json())
              .then(data => ({ data }));
      }
      

三、泛型的类型约束

  1. 为什么需要类型约束

    • 增强类型安全:类型约束可以限制泛型参数的类型范围,避免类型不匹配的错误。
    • 提高代码的灵活性和复用性:通过类型约束,可以编写更灵活的代码,使得同一函数或类可以适应多种类型,同时确保类型的一致性。约束泛型使得代码更通用,同时能够接受不同的类型并在限制范围内进行操作。
  2. 类型约束的实现方式

    • 使用extends关键字限制类型范围。

    • 示例

      interface Lengthwise {
          length: number;
      }
      function logLength<T extends Lengthwise>(item: T): void {
          console.log(item.length);
      }
      logLength({ length: 10 }); // 正确
      logLength(5); // 错误
      
  3. 多重约束与条件类型

    • 通过多重约束和条件类型增加代码灵活性。

    • 示例

      function mergeObjects<T extends object, U extends object>(obj1: T, obj2: U): T & U {
          return { ...obj1, ...obj2 };
      }