返回

TS泛型:让代码更加灵活,轻松应对各种数据类型

前端

泛型:TypeScript 中的可重用、类型无关的构建块

泛型在 TypeScript 中扮演着至关重要的角色,它是一项强大的功能,可以帮助你编写可重用的代码,而不用担心数据类型。想象一下,你正在搭建一个乐高积木,它能根据你插入的不同块而调整形状和大小。泛型就像乐高的连接点,它们可以根据传入的数据类型自动适应,从而创建出可适用于各种类型数据的灵活组件。

类型变量:泛型的通用语言

泛型使用类型变量(用尖括号 <> 表示)来表示任何类型。就像在数学中,我们使用 x、y 和 z 来表示数字一样,泛型类型变量表示任何数据类型。这使得你可以编写代码,而无需事先指定特定类型。

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

上面的 identity 函数接受任何类型的值,并返回该值,而不管它是什么类型。<T> 表示一个可以是任何类型的类型变量。

约束:为类型变量设置边界

有时,你可能希望限制泛型可以接受的类型。约束就像安全网,它们可以确保你只接受特定的类型组合。

function identity<T extends string | number>(value: T): T {
  return value;
}

现在,identity 函数只能处理字符串或数字类型。<T extends string | number> 约束确保 T 只可能是这两者之一。

函数:用泛型创建多功能函数

泛型与函数搭配得天衣无缝。你可以使用它们来创建可以处理任何类型数据的函数。

function map<T, U>(array: T[], fn: (value: T) => U): U[] {
  return array.map(fn);
}

map 函数接受一个数组和一个转换函数,并返回一个包含转换后元素的新数组。<T, U> 泛型表示输入数组类型和输出数组元素类型。

对象:泛型的通用容器

泛型可以让你创建可存储任何类型数据的对象。它们就像可变尺寸的盒子,可以适应你放入其中的任何东西。

interface Box<T> {
  value: T;
}

Box 接口定义了一个可以存储任何类型 T 的对象。你可以创建 Box<string> 来存储字符串,Box<number> 来存储数字,等等。

数组:用泛型跟踪类型

数组也可以受益于泛型。它可以确保你只存储特定类型的元素,从而防止类型混乱。

let array: Array<T> = [];

array 数组只能包含 T 类型的元素。你可以创建 Array<string> 来存储字符串,Array<number> 来存储数字,等等。

迭代器:泛型的遍历工具

泛型可以为你的迭代器增添灵活性。它们可以让你遍历任何类型的数据序列。

function* generator<T>(array: T[]): IterableIterator<T> {
  for (const value of array) {
    yield value;
  }
}

generator 函数返回一个迭代器,它可以遍历任何类型的数据数组。<T> 泛型确保迭代器只能遍历 T 类型的元素。

映射:泛型的键值对仓库

映射就像字典,它们使用键值对存储数据。泛型可以确保键和值具有特定的类型。

let map: Map<string, T> = new Map();

map 映射只能存储具有字符串键和 T 类型值的键值对。你可以创建 Map<string, number> 来存储字符串键和数字值,等等。

扩展:用泛型扩展类型

泛型甚至可以让你扩展类型,就像给现有的类或接口添加新功能一样。

class Wrapper<T> {
  constructor(private value: T) {}

  getValue(): T {
    return this.value;
  }
}

Wrapper 类用泛型类型 T 扩展了任何类型的对象。你可以用 Wrapper<string> 来扩展字符串,用 Wrapper<number> 来扩展数字,等等。

keyof 操作符:泛型的类型提取器

keyof 操作符与泛型携手合作,让你可以提取指定类型的键。

type PersonKeys = keyof Person;

假设你有一个 Person 接口,PersonKeys 类型将包含该接口的所有键的集合。你可以用它来访问 Person 类型的所有属性。

结论:泛型的力量

泛型是 TypeScript 中一项真正强大的工具,它可以让你创建可重用的、类型无关的组件。它们就像乐高的连接点,可以连接各种数据类型,构建强大而灵活的应用程序。利用泛型的强大功能,你可以节省时间,编写更健壮的代码,并应对各种编程挑战。

常见问题解答

  1. 什么是泛型?
    泛型是 TypeScript 中的数据类型变量,可以表示任何类型。它们可以用于创建可重用的代码,而不用担心数据类型。

  2. 如何定义泛型?
    泛型使用尖括号 <> 定义。例如,<T> 表示一个泛型类型变量,它可以是任何类型。

  3. 为什么使用泛型?
    泛型可以让你编写可重用的代码,无论数据类型如何。它们还可以帮助你避免类型错误并提高代码质量。

  4. 泛型有哪些类型?
    TypeScript 中有各种泛型,包括函数泛型、对象泛型、数组泛型、迭代器泛型、映射泛型和扩展泛型。

  5. 我如何使用 keyof 操作符与泛型?
    keyof 操作符可以与泛型一起使用,以提取指定类型的键。例如,keyof Person 将返回一个包含 Person 类型所有键的类型。