青训营X豆包MarsCode 技术训练营 前端实践选题 |豆包MarsCode AI 刷题

28 阅读3分钟

以下是一份关于TypeScript类与泛型的使用实践记录,涵盖泛型使用方法、场景以及类型约束相关要点。

泛型基础概念与使用方法

泛型是TypeScript中强大的特性,允许编写可复用且灵活的代码,能够处理多种数据类型,而不是局限于特定的单一类型。在定义函数、类或者接口时,通过使用类型参数(通常用尖括号包裹,如)来表示泛型。

例如,定义一个简单的函数,用于返回传入参数本身,不局限于特定类型: function identity(arg: T): T { return arg; } // 使用示例 let output1 = identity("hello"); // 明确指定类型为 string,返回值类型也是 string let output2 = identity(42); // 不指定类型,TypeScript会自动推断类型为 number,返回值类型也是 number 在类中使用泛型同样很常见。比如创建一个简单的Box类,用来存储任意类型的数据: class Box { private value: T; constructor(item: T) { this.value = item; } getValue(): T { return this.value; } } // 使用示例 let box1 = new Box("TypeScript"); console.log(box1.getValue()); // 输出 "TypeScript",类型为 string let box2 = new Box(123); console.log(box2.getValue()); // 输出 123,类型为 number 泛型使用场景

  1. 数据结构与算法:在实现如数组、链表、栈、队列等数据结构时,泛型发挥关键作用。以自定义数组类为例,能操作不同类型元素: class MyArray { private data: T[] = []; add(item: T): void { this.data.push(item); } get(index: number): T { return this.data[index]; } } let numArray = new MyArray(); numArray.add(1); numArray.add(2); let strArray = new MyArray(); strArray.add("a"); strArray.add("b"); 这种设计使得代码不必为每种数据类型重复编写类似逻辑,提升复用性。
  2. 函数式编程辅助:像高阶函数map、filter等,借助泛型处理不同类型数组元素转换与筛选。假设实现map函数: function map<T, U>(array: T[], callback: (item: T) => U): U[] { return array.map(callback); } let numbers = [1, 2, 3]; let doubled = map(numbers, (n) => n * 2); // 类型推断下,doubled 为 number[]
  3. 接口与抽象类通用化:在定义接口规范或者抽象类骨架供子类实现时,泛型可让规则适配多类型场景。例如设计可存储不同类型键值对的存储接口: interface KeyValueStore<T, U> { set(key: T, value: U): void; get(key: T): U | undefined; } class InMemoryStore<T, U> implements KeyValueStore<T, U> { private store: Map<T, U> = new Map(); set(key: T, value: U): void { this.store.set(key, value); } get(key: T): U | undefined { return this.store.get(key); } } 类型约束增加灵活性与安全性

类型约束通过extends关键字实现,限制泛型类型参数必须符合特定条件,增强代码健壮性。

  1. 接口约束:如果要确保泛型类型有特定方法或属性,可用接口约束。如创建一个打印对象详细信息的函数,要求对象有toString方法: interface Printable { toString(): string; } function printDetails(obj: T): void { console.log(obj.toString()); } class Person { constructor(public name: string, public age: number) {} toString(): string { return Name: ${this.name}, Age: ${this.age}; } } let person = new Person("Alice", 30); printDetails(person); // 正常打印对象信息,确保传入对象符合 Printable 接口规范
  2. 类继承约束:在处理继承体系时,利用类型约束控制泛型适配范围。假设有基类Shape和子类Circle、Rectangle: class Shape { draw(): void { console.log("Drawing a shape"); } } class Circle extends Shape { draw(): void { console.log("Drawing a circle"); } } class Rectangle extends Shape { draw(): void { console.log("Drawing a rectangle"); } } function drawShapes(shapes: T[]): void { shapes.forEach((shape) => shape.draw()); } let circles: Circle[] = [new Circle(), new Circle()]; drawShapes(circles); // 正确调用,保证传入是 Shape 或其子类实例数组 通过合理运用泛型及类型约束,TypeScript代码能在保持灵活、可复用同时,有效规避类型错误,提升整体安全性与可维护性,适应复杂多变开发需求。