JavaScript中的泛型:初学者需要了解的原因及使用方法

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

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

开始课程

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

\n\n

想象一下,你正在编写一个需要处理不同类型数据(数字、字符串、对象)的函数。如果没有泛型,你将不得不重复代码或使用any,从而失去对类型的控制。泛型是一种机制,允许你创建能够处理任何数据类型但保留类型信息的组件(函数、类、接口)。

\n\n

尽管JavaScript是一种动态类型语言,但在Node.js生态系统中广泛使用TypeScript,它增加了静态类型检查。正是在TypeScript中,泛型得以充分发挥其威力。然而,理解泛型的原理对于纯JavaScript也很有用——尤其是当你编写库或使用现代框架时。

\n\n

在本文中,我们将讨论:

\n
    \n
  • 为什么需要泛型
  • \n
  • 如何在TypeScript中声明和使用泛型
  • \n
  • Node.js示例(API、数据处理)
  • \n
  • 限制和最佳实践
  • \n
\n\n

泛型基础:语法和基本示例

\n\n

第一个泛型:identity函数

\n\n

经典示例——一个返回输入值的函数:

\n\n
// 没有泛型\nfunction identity(value: any): any {\n  return value;\n}\n\n// 使用泛型\nfunction identity<T>(value: T): T {\n  return value;\n}\n\n// 使用\nconst num = identity<number>(42);    // num — number\nconst str = identity<string>('hello'); // str — string\n
\n\n

符号<T>是类型参数。你可以随意命名它(T、U、Item),但传统上使用T(代表Type)。

\n\n

多参数泛型

\n\n

有时需要同时处理多个类型:

\n\n
function pair<T, U>(first: T, second: U): [T, U] {\n  return [first, second];\n}\n\nconst result = pair<number, string>(1, 'one');\n// result: [number, string]\n
\n\n

箭头函数中的泛型(Node.js)

\n\n

在React或工具函数中,经常使用带泛型的箭头函数:

\n\n
const wrapInArray = <T>(item: T): T[] => {\n  return [item];\n};\n\nconst arr = wrapInArray('test'); // arr: string[]\n
\n\n

在真实Node.js项目中应用泛型

\n\n

带类型化响应的API处理器

\n\n

想象一下,你正在编写一个用于API请求的通用函数。没有泛型,你会丢失数据类型:

\n\n
// 不好:any\nasync function fetchData(url: string): Promise<any> {\n  const response = await fetch(url);\n  return response.json();\n}\n\n// 好:泛型\nasync function fetchData<T>(url: string): Promise<T> {\n  const response = await fetch(url);\n  return response.json();\n}\n\n// 使用\ninterface User {\n  id: number;\n  name: string;\n}\n\nconst user = await fetchData<User>('/api/user/1');\nconsole.log(user.name); // TypeScript知道name是string\n
\n\n

类型化数据集合

\n\n

在处理数据库时(例如通过Prisma或Mongoose),泛型有助于创建通用存储库:

\n\n
class Repository<T extends { id: number }> {\n  private items: T[] = [];\n\n  add(item: T): void {\n    this.items.push(item);\n  }\n\n  getById(id: number): T | undefined {\n    return this.items.find(item => item.id === id);\n  }\n}\n\n// 使用\ninterface Product {\n  id: number;\n  title: string;\n  price: number;\n}\n\nconst productRepo = new Repository<Product>();\nproductRepo.add({ id: 1, title: 'Laptop', price: 1000 });\nconst laptop = productRepo.getById(1);\n
\n\n

错误处理包装器

\n\n

一个用于

博客

书籍推荐