TypeScript 泛型与函数重载:解决排序类型推断问题
本文介绍如何在 TypeScript 中结合使用泛型与函数重载来优化排序功能。通过对比 ts-node 与 tsc 运行环境,演示如何针对中英文数组分别处理,并利用函数重载解决返回联合类型导致的类型推断模糊问题,使返回值类型更加精确,提升开发体验。
前言
在使用 TypeScript 进行开发的过程中,起初可能觉得它与 Java 相似,但随着深入会发现两者存在显著差异。尽管概念上有共通之处,例如泛型,但 TypeScript 的函数重载机制与 Java 截然不同。本文将通过一个排序功能的实现案例,深入探讨 TypeScript 中泛型与函数重载的具体应用。
TypeScript 的运行环境
1. ts-node
ts-node 是 TypeScript 的 Node.js 解释器与执行工具,允许直接运行 TypeScript 代码,其作用类似于 Node.js 执行 JavaScript 文件。
使用方法十分简便:在项目中安装 typescript 和 ts-node 依赖后,通过 ts-node 命令即可执行 .ts 文件。
1.在命令行安装依赖
npm install typescript ts-node
2.使用 ts-node 运行 ts 文件(这里使用 npx 来执行 ts-node,因为 ts-node 是在本地项目中安装的,如果直接使用的话会报命令找不到的错误,当然如果在全局安装了 ts-node npm 包就直接可以使用 ts-node 来运行,如果只是本地安装了,那么需要加上 npx,这是会到 node_modules 文件夹中找到 ts-node 包来进行执行。)
全局安装了: ts-node: ts-node xxx.ts 本地项目安装了 ts-node: npx ts-node xxx.ts
补充: ts-node 也可以直接在命令行中编写和执行 ts 代码,像 python 那样,
如下图:

2. tsc
tsc 是 TypeScript 的编译器名称。安装 TypeScript 后,可使用 tsc 命令处理 .ts 文件。与 ts-node 不同,tsc 仅将 TypeScript 代码编译为 JavaScript 文件,随后需通过 Node.js 执行生成的 JS 文件。
tsc 支持丰富的配置项。运行 tsc --init 可在项目中生成 tsconfig.json 文件,其中包含编译输出路径、模块规范以及 ES6 语法兼容性等配置选项。
//1.安装 typescript
npm install typescript
//2.使用 tsc 生成 tsconfig.json 文件
npx tsc --init
//3.使用 tsc 编译 ts 文件
npx tsc xxx.tsTypeScript 中的函数重载
TypeScript 中的函数重载与其他语言(如 Java)不同。它更像是一种“伪重载”,并非为了实现同名但参数个数不同的函数,而是主要服务于类型推断。
简单的排序算法
首先,使用 TypeScript 实现一个快速排序函数:
1. 快速排序
function quickSort<T>(arr: Array<T>): T[] {
if (arr.length < 2) return arr
const left: Array<T> = []
const right: Array<T> = []
const mid = arr.splice(Math.floor(arr.length / 2), 1)[0]
for (let item of arr) {
if (item < mid) {
left.push(item)
} else {
right.push(item)
}
}
return quickSort(left).concat(mid, quickSort(right))
}上述代码展示了使用泛型实现的快速排序函数。快速排序性能优于冒泡排序,其核心思想是分治法:选取一个元素作为基准,将数组分为小于和大于该元素的两部分,递归处理这两部分,最终合并结果。
上述快速排序代码在处理英文数组时表现正常,但若传入中文数组则无法正确排序。因此,中文数组需要单独处理,使用以下函数:
2. 中文排序
// 通过正则表达式,判断是否是中文数组
function isChinese<T>(arr: Array<T>): boolean {
const pattern = /[\u4e00-\u9fa5]+/g;
return arr.some((item: any) => {
return pattern.test(item)
})
}
// 中文排序
function chineseSort<T>(arr: Array<T>): T[] {
return arr.sort((first, second) => {
return (first as any).localeCompare(second, 'zh-CN')
})
}对于中文数组,使用数组内置的 sort 函数进行排序。
接下来,若需对英文数组中的每一项字符串进行排序,则还需要单独的函数进行处理:
3. 字符串自排序
// 英文自排序
function strSelfSort(str: string): string {
const strArr = str.split('')
return quickSort(strArr).join('')
}实现英文字符串自排序的逻辑是:先将字符串 split 分割为字符数组,传入前述快速排序函数处理,得到结果后再通过 join 函数拼接成字符串返回。
那么,接下来将上面的几种排序功能整合成一个单独的通用函数:
4. 通过泛型整合几种排序
// 通用的排序函数
function sort<T>(data: T): T[] | string {
if (typeof data === "string") {
return strSelfSort(data)
}
if (data instanceof Array) {
if (isChinese(data)) {
return chineseSort(data)
}
const newArr = data.map((item) => {
return typeof item === "string" ? strSelfSort(item) : item
})
return quickSort(newArr)
}
throw new Error(`data must be string or array. ${data}`)
}通过上述通用排序函数可以看出,在函数内部根据传递的数据类型进行判断:如果是 string 类型,则调用自排序;如果是数组,则进一步判断是否为中文数组。若是中文数组,调用中文排序函数;否则视为英文数组。对于英文数组,先使用 map 遍历,若元素为 string 类型则调用字符串自排序,否则原样返回,最后通过快速排序函数处理,从而实现英文数组整体及内部元素的排序。
虽然上述排序函数功能较为完善,但存在一个不足之处:该函数返回联合类型 T[] | string。这导致通过该函数排序后的结果无法确切推断具体类型,只能得到联合类型,从而只能使用联合类型中共有的方法提示。
如下图:


这里简单的调用了一下写好的排序函数,返回的结果类型竟然是:string | string[][] 的联合类型,这样的返回结果对于开发后续功能来说很不友好,那么接下来,就使用 TS 中的函数重载来完善一下上面的排序函数:
5. 使用函数重载完善排序功能
// 使用函数重载重构排序函数
function sort(data: string): string
function sort<T>(data: T): T
function sort(data: any): any {
if (typeof data === "string") {
return strSelfSort(data)
}
if (data instanceof Array) {
if (isChinese(data)) {
return chineseSort(data)
}
const newArr = data.map((item) => {
return typeof item === "string" ? strSelfSort(item) : item
})
return quickSort(newArr)
}
throw new Error(`data must be string or array. ${data}`)
}关于 TS 的函数重载,就是只有一个实现的函数,其余都是函数签名,而且必须放在实现函数的上面,在调用这个函数的时候,只会显示上面的函数签名函数,而不会展示具体实现的函数,但是实际执行的却是那个实现函数,在这种情况下,通过使用函数重载写个两个不同参数和返回值的函数签名提供给调用者使用,而在具体实现函数中去兼容处理,这样做的好处就是调用者得到的返回值类型可以是某个具体的类型了,而不再是个联合类型,更有益于后面的开发。
总结
通过使用 TS 的函数重载解决了当一个函数返回一个联合类型时,类型推断不确定的问题,在某些会返回联合类型的场景下可以尝试使用,方便后续的类型推断操作,所以说,TS 的一切真的都是为类型而服务的,怎么写好 TS 代码其实就是在更好的完善类型推断,类型系统的过程,只有更好更准确的类型推断,才能发挥 TS 的作用,让编译器在开发过程中智能的告诉开发者有哪些属性和方法可以调用,并且在调用了错误的属性和方法后可以及时提醒开发者。
到此这篇关于TypeScript 泛型重载函数的使用方式的文章就介绍到这了,更多相关TypeScript 泛型重载函数 内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
JavaScript怎么准确判断数据类型:typeof、instanceof与Object.prototype.toString
2026-11-05 17:09:21
JS中将数组和对象混合组装为JSON字符串
2026-11-05 16:41:42
JS运算符优先级与结合性的区别是什么?
2026-11-05 13:22:02
JS Map怎么只遍历Key或Value
2026-11-05 13:00:36
D3.js 与 ECharts 选型对比:灵活性 vs 开发效率
2026-11-05 09:45:01








