返回

TypeScript 泛型使用注意事项

前端

在上一节中,我们了解了 TypeScript 中泛型的基础使用。这一节,我们来探讨使用泛型时需要注意的一些问题。

泛型变量

泛型变量就像普通变量一样,可以存储任何类型的值。但是,泛型变量有一个重要的区别:它们可以存储不同类型的值。例如,我们可以定义一个泛型变量 T,它可以存储任何类型的值:

let t: T;

我们可以将任何类型的值赋给 t

t = 123; // 存储一个数字
t = "hello"; // 存储一个字符串
t = true; // 存储一个布尔值

类型约束

有时,我们希望泛型变量只能存储特定类型的值。我们可以使用类型约束来实现这一点。例如,我们可以定义一个泛型变量 T,它只能存储数字值:

let t: T extends number;

现在,我们只能将数字值赋给 t

t = 123; // 存储一个数字
// t = "hello"; // 错误:不能将字符串值赋给 T
// t = true; // 错误:不能将布尔值赋给 T

协变和逆变

协变和逆变是泛型类型的两个重要概念。协变意味着子类型可以分配给父类型。逆变意味着父类型可以分配给子类型。

泛型函数

泛型函数可以接受任何类型的参数,并返回任何类型的返回值。例如,我们可以定义一个泛型函数 max,它返回两个值中的较大值:

function max<T>(a: T, b: T): T {
  return a > b ? a : b;
}

我们可以使用 max 函数来比较任何类型的两个值:

max(123, 456); // 返回 456
max("hello", "world"); // 返回 "world"
max(true, false); // 返回 true

泛型类

泛型类可以创建可以存储任何类型的值的实例。例如,我们可以定义一个泛型类 List,它存储一组值:

class List<T> {
  private items: T[];

  constructor(...items: T[]) {
    this.items = items;
  }

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

  get(index: number): T {
    return this.items[index];
  }
}

我们可以使用 List 类来创建存储任何类型的值的实例:

const list1 = new List<number>(1, 2, 3);
const list2 = new List<string>("hello", "world", "!");

结论

泛型是 TypeScript 中一项强大的功能,它允许我们创建可重用的代码,而无需重复相同的代码多次。在使用泛型时,需要注意一些事项,包括泛型变量、类型约束、协变和逆变、泛型边界、泛型函数和泛型类。通过理解这些注意事项,我们可以更有效地使用 TypeScript 泛型。