TypeScript 中的泛型:完整使用指南

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

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

开始课程

TypeScript 泛型介绍



TypeScript 是一种强类型编程语言,它为 JavaScript 添加了静态类型检查。TypeScript 最强大且常被低估的特性之一是 Generics(泛型,通用类型)。如果你曾经编写过需要处理不同数据类型的函数,或者创建过需要通用的组件,那么泛型正是你所需要的。



在本文中,我们将详细探讨 TypeScript 中的泛型是什么、为什么需要它们以及如何在实际中使用它们。你将学习如何使你的代码更灵活、更安全且更可复用。



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



Generics(泛型,通用类型) 是一种机制,它允许你创建能够处理不同数据类型且不丢失类型信息的组件(函数、类、接口)。想象一下,你正在编写一个返回数组第一个元素的函数。没有泛型,你将不得不使用 any 类型,这会让你失去强类型检查的优势。



为什么使用泛型?

  • 类型安全: TypeScript 在编译时检查类型,防止错误。
  • 代码复用: 一个函数或类可以处理任何数据类型。
  • 提高可读性: 代码变得更清晰且具有自文档性。
  • 减少重复: 你不需要为每种数据类型编写单独的函数。


没有泛型,你可能会写出类似这样的代码:



// 不好:丢失了类型信息function getFirstElement(arr: any[]): any {  return arr[0];}

const num = getFirstElement([1, 2, 3]); // 类型 anyconsole.log(num.toUpperCase()); // 运行时错误!


使用泛型,代码变得安全且灵活:



// 好:保留了类型function getFirstElement<T>(arr: T[]): T | undefined {  return arr[0];}

const num = getFirstElement([1, 2, 3]); // 类型 numberconst str = getFirstElement(['a', 'b', 'c']); // 类型 string

// num.toUpperCase(); // 编译错误!number 没有 toUpperCase 方法


泛型基础语法



尖括号语法



泛型使用尖括号 <> 来指定类型参数。通常参数用单个字母表示:T (Type), U, V 等。但是,你可以使用任何有意义的名称。



// 最简单的例子:带一个类型参数的函数function identity<T>(arg: T): T {  return arg;}

// 显式指定类型let result1 = identity<string>('Hello');

// 类型推断(TypeScript 自动确定类型)let result2 = identity(42); // 类型 number


多个类型参数



你可以在一个函数或类中使用多个类型参数:



function merge<T, U>(obj1: T, obj2: U): T & U {  return { ...obj1, ...obj2 };}

const merged = merge({ name: 'John' }, { age: 30 });// 类型:{ name: string } & { age: number }console.log(merged.name); // Johnconsole.log(merged.age); // 30


约束(Constraints)



有时需要限制可以传递给泛型的类型。为此,使用关键字 extends:



interface HasLength {  length: number;}

// 该函数仅适用于具有 length 属性的类型function logLength<T extends HasLength>(arg: T): T { console.log(arg.length); return arg;}

logLength('Hello'); // 有效:5logLength([1, 2, 3]); // 有效:3// logLength(123); // 错误!number 没有 length


泛型的应用

博客

书籍推荐