JavaScript中的泛型:为什么需要以及如何使用

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

JavaScript中的泛型:为什么需要它们以及如何使用



在现代JavaScript和Node.js开发世界中,泛型的概念越来越常见。虽然原生JavaScript不支持严格类型检查,但TypeScript和JSDoc等工具允许您实现强大的泛型编程机制。在本文中,我们将详细解析为什么需要泛型,它们在Node.js上下文中如何工作,以及如何正确使用它们。



什么是泛型以及为什么需要它们?



泛型是一种机制,允许您创建能够处理不同数据类型同时保持严格类型检查的组件(函数、类、接口)。无需为数字、字符串和数组分别编写相同的函数,您只需编写一个通用的代码片段。



泛型的主要优点:

  • 类型安全 — 类型错误在编译/检查阶段被捕获,而非运行时。
  • 代码复用 — 一个函数适用于任何数据类型。
  • 可读性 — 代码具有自文档化特性。
  • IDE集成 — 自动补全和类型提示能够正确工作。


在Node.js中,泛型在操作数据库、API请求、数据集合和工具函数时尤其有用。



TypeScript中的泛型(主要方式)



TypeScript是JavaScript的超集,添加了静态类型检查。正是在TypeScript中,泛型得到了最充分的实现。让我们看看基本语法。



简单的泛型函数



// 没有泛型——必须使用anyfunction identity(arg: any): any {    return arg;}

// 使用泛型——类型被保留function identity<T>(arg: T): T { return arg;}

// 使用const num = identity<number>(42); // 类型 numberconst str = identity<string>("hello"); // 类型 string


尖括号 <T> — 这是类型参数的声明。T 是约定俗成的名称;可以是任何内容(通常使用 T、U、V)。



带数组的泛型



最常见的场景之一就是操作数组:



// 返回数组第一个元素的函数function getFirst<T>(arr: T[]): T | undefined {    return arr[0];}

const firstNumber = getFirst([1, 2, 3]); // numberconst firstString = getFirst(["a", "b", "c"]); // string


多重类型



您可以使用多个类型参数:



function pair<T, U>(first: T, second: U): [T, U] {    return [first, second];}

const result = pair(42, "answer"); // 类型 [number, string]


泛型中的约束



有时您需要限制哪些类型可以被使用。为此,使用带有关键字 extends 的约束。



// 仅适用于具有 length 属性的对象的函数function getLength<T extends { length: number }>(arg: T): number {    return arg.length;}

getLength("hello"); // 5 — 字符串有 lengthgetLength([1, 2, 3]); // 3 — 数组有 length// getLength(42); // 错误!数字没有 length


这在Node.js中操作缓冲区、字符串和数组时尤其有用——任何具有 length 属性的对象。



类和接口中的泛型



泛型不仅适用于函数,也适用于类和接口。



泛型类



Node.js中简单栈的示例:



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

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

pop(): T | undefined { return this.items.pop

博客

书籍推荐