返回

TypeScript 泛型,包教包会!

前端

前言

TypeScript 泛型是一把双刃剑。用好了,它能让你的代码简洁、优雅、可读性强;用不好,它就会变成一个烫手山芋,让你的代码变得难以理解和维护。

如果你正在学习 TypeScript,或者已经使用 TypeScript 一段时间了,但还对泛型感到困惑,那么这篇文章正是为你而写的。在本文中,我将以通俗易懂的语言,从基础概念到高级用法,带你全面了解 TypeScript 泛型。

什么是泛型?

泛型是一种允许你为函数或类定义参数化类型的方法。参数化类型是指一种类型,它可以在定义时接受一个或多个类型参数。例如,你可以定义一个函数 add(),它可以接受两个任意类型的参数,并返回这两个参数的和。

function add<T>(a: T, b: T): T {
  return a + b;
}

在这个函数中,<T> 是一个类型参数。它可以是任何类型。例如,你可以调用 add() 函数,并传入两个数字,它将返回这两个数字的和:

const sum = add(1, 2); // sum 为 number 类型

你也可以调用 add() 函数,并传入两个字符串,它将返回这两个字符串的连接:

const str = add("hello", "world"); // str 为 string 类型

泛型的优势

泛型具有以下几个优势:

  • 代码复用性: 泛型可以让你编写可重用的代码。例如,你可以编写一个 max() 函数,它可以接受两个任意类型的参数,并返回这两个参数中的最大值。你可以使用这个函数来查找数字、字符串或任何其他可比较类型中的最大值。
  • 类型安全: 泛型可以帮助你提高代码的类型安全性。在上面的 add() 函数中,类型参数 T 确保了函数只能接受两种相同类型的参数。这可以防止你犯下类型错误,例如将数字与字符串相加。
  • 可读性: 泛型可以提高代码的可读性。当你在使用泛型时,你不需要显式地指定函数或类的类型参数。这使得你的代码更加简洁和易于理解。

泛型的使用

泛型可以用于函数、类和接口。

泛型函数

你可以通过在函数名前面加上类型参数列表来定义一个泛型函数。例如,以下是一个计算两个数字和的泛型函数:

function add<T>(a: T, b: T): T {
  return a + b;
}

这个函数可以接受两个任意类型的参数,并返回这两个参数的和。

泛型类

你可以通过在类名前面加上类型参数列表来定义一个泛型类。例如,以下是一个表示栈的泛型类:

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

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

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

  peek(): T | undefined {
    return this.stack[this.stack.length - 1];
  }

  isEmpty(): boolean {
    return this.stack.length === 0;
  }
}

这个类可以存储任何类型的元素。你可以使用这个类来创建一个数字栈、一个字符串栈或任何其他类型的栈。

泛型的约束

在某些情况下,你可能希望对泛型类型参数进行约束。例如,你可能希望确保泛型类型参数只能是数字。你可以通过使用类型约束来实现这一点。

以下是如何对泛型类型参数进行约束:

function add<T extends number>(a: T, b: T): T {
  return a + b;
}

在这个函数中,类型参数 T 被约束为只能是数字类型。这意味着你只能调用这个函数,并传入两个数字参数。

结语

泛型是 TypeScript 中一个非常强大的特性。它可以让你编写更灵活、更可重用和更类型安全的代码。我希望本文能帮助你更好地理解泛型,并开始在你的 TypeScript 代码中使用它。