返回

TypeScript 泛型之 K、T、V 等到底是个啥?

前端

TypeScript 泛型基础

泛型是一个允许您在类型系统中使用参数的特性。这使得您可以编写可处理任何类型数据的代码。泛型在 TypeScript 中使用尖括号 <> 表示。

泛型变量是泛型类型的一部分。它们允许您在代码中使用类型变量,而无需指定实际类型。例如,以下函数使用泛型变量 T 来表示输入和输出类型:

function identity<T>(x: T): T {
  return x;
}

此函数可以与任何类型的数据一起使用。例如,您可以将其用于数字、字符串或数组:

identity(1); // 返回 1
identity("Hello"); // 返回 "Hello"
identity([1, 2, 3]); // 返回 [1, 2, 3]

泛型类型是一种使用泛型变量定义的类型。泛型类型可以是类、接口或函数。例如,以下类使用泛型变量 T 来表示存储的数据类型:

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

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

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

此类可以用于存储任何类型的数据。例如,您可以使用它来存储数字、字符串或对象:

const numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
numberStack.push(3);

const stringStack = new Stack<string>();
stringStack.push("Hello");
stringStack.push("World");
stringStack.push("!");

const objectStack = new Stack<object>();
objectStack.push({ name: "John Doe" });
objectStack.push({ age: 30 });
objectStack.push({ city: "New York" });

泛型约束

泛型约束允许您限制泛型变量可以使用的类型。例如,以下函数使用泛型约束来确保 T 类型的变量只能是数字:

function sumNumbers<T extends number>(...numbers: T[]): number {
  return numbers.reduce((acc, curr) => acc + curr, 0);
}

此函数只能用于数字类型的数据。例如,您可以将其用于计算数字数组的和:

sumNumbers(1, 2, 3); // 返回 6
sumNumbers(1.2, 2.3, 3.4); // 返回 6.9

但您不能将字符串或对象传递给此函数,因为它们不满足泛型约束:

sumNumbers("Hello", "World"); // 错误:参数类型“string”不能分配给类型“number”
sumNumbers({ name: "John Doe" }, { age: 30 }); // 错误:参数类型“object”不能分配给类型“number”

泛型的常见类型变量

在 TypeScript 中,有几个常用的泛型类型变量:

  • T:表示类型变量。它可以是任何类型的数据。
  • K:表示键类型变量。它通常用于表示对象的键类型。
  • V:表示值类型变量。它通常用于表示对象的键类型。
  • U:表示另一个类型变量。它通常用于表示函数的返回值类型。

泛型的优点

泛型具有许多优点,包括:

  • 可重用性:泛型代码可以重用于不同的类型数据,而无需重新编写。
  • 类型安全:泛型可以帮助您捕获类型错误,从而使您的代码更加健壮。
  • 可扩展性:泛型代码可以很容易地扩展到新的类型数据。

泛型的局限性

泛型也有一些局限性,包括:

  • 复杂性:泛型代码可能比非泛型代码更难理解和维护。
  • 性能:泛型代码可能比非泛型代码性能更低。

总结

泛型是 TypeScript 中一项强大的特性,它可以帮助您编写可重用、类型安全和可扩展的代码。虽然泛型代码可能比非泛型代码更难理解和维护,但它的优点通常超过了它的缺点。