TypeScript 类、泛型的使用实践记录 | 青训营

92 阅读3分钟

TypeScript 是一种静态类型的 JavaScript 超集,它提供了更强大的类型系统和类型推断能力。在 TypeScript 中,我们可以使用泛型来增加代码的灵活性和安全性。泛型是一种参数化类型的机制,它允许我们在定义函数、类或接口时使用类型变量,以在使用时动态指定具体的类型。

以下是一些使用 TypeScript 类和泛型的实践记录,探讨泛型的使用方法和场景,以及如何使用类型约束来增加代码的灵活性和安全性。

1. 泛型函数

泛型函数允许我们在调用函数时指定参数的类型,并在函数内部使用指定的类型进行操作。例如,我们可以编写一个泛型函数来交换两个变量的值:

function swap<T>(a: T, b: T): void {
  let temp: T = a;
  a = b;
  b = temp;
}

let x: number = 1;
let y: number = 2;

swap<number>(x, y);
console.log(x, y); // 输出 2, 1

在上述代码中,swap 函数使用了类型变量 T 来接收传入的参数类型,并在函数内部使用这个类型进行操作。在调用 swap 函数时,我们使用 <number> 来指定参数的类型为 number,从而交换了 xy 的值。

2. 泛型类

泛型类允许我们在定义类时使用类型变量,并在类的属性和方法中使用指定的类型。例如,我们可以创建一个用于存储任意类型数据的栈数据结构:

class Stack<T> {
  private data: T[] = [];

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

  pop(): T | undefined {
    return this.data.pop();
  }
}

let stack = new Stack<number>();
stack.push(1);
stack.push(2);
console.log(stack.pop()); // 输出 2

let stringStack = new Stack<string>();
stringStack.push('hello');
stringStack.push('world');
console.log(stringStack.pop()); // 输出 'world'

在上述代码中,Stack 类使用类型变量 T 来接收存储的数据类型,并使用这个类型变量在类的属性和方法中指定类型。这样我们可以创建一个存储 number 类型的栈和一个存储 string 类型的栈。

3. 泛型约束

通过使用类型约束,我们可以限制泛型变量的类型范围,以增加代码的灵活性和安全性。例如,我们可以编写一个函数来计算并返回数组中最大值的索引:

function findMaxIndex<T extends { value: number }>(array: T[]): number {
  let maxIndex = 0;
  for (let i = 1; i < array.length; i++) {
    if (array[i].value > array[maxIndex].value) {
      maxIndex = i;
    }
  }
  return maxIndex;
}

let values = [{ value: 10 }, { value: 5 }, { value: 8 }];
console.log(findMaxIndex(values)); // 输出 0

在上述代码中,我们通过使用类型约束 T extends { value: number },限制了 T 的类型必须拥有 value 属性且为 number 类型。这样我们可以确保传入的数组中的元素具有 value 属性,并且可以进行比较以找到最大值的索引。

泛型在 TypeScript 中的应用场景非常广泛,可用于函数、类、接口等多个方面。使用泛型可以提高代码的灵活性和安全性,可以根据实际需要动态指定参数和返回值的类型,同时通过类型约束可以限制类型的范围和功能的适用性。在实际开发过程中,我们可以根据具体的需求合理地使用泛型来提高代码的质量和可维护性。