TypeScript?泛型重載函數(shù)的使用方式
前言
使用 TypeScript 進(jìn)行開發(fā)也已經(jīng)有段日子了,雖然最開始接觸后以為這不就和 Java 一樣一樣的么,然而越深入了解越發(fā)現(xiàn)還真不一樣~不過有些概念來說是相通的,比如泛型。 Java 里也有函數(shù)重載,但是和 TS 差別還是挺大的,那就通過一個排序功能來了解一下 TS 中的泛型重載吧
TypeScript 的運行環(huán)境
1. ts-node
ts-node 是 typescript 的 node.js 解釋和執(zhí)行器,也就是說,它可以像 node 執(zhí)行 JavaScript 一樣執(zhí)行 typescript 代碼。
使用方式也很簡單,在項目中安裝 typescript 和 ts-node 的依賴后使用 ts-node 命令執(zhí)行 ts 文件即可。
1.在命令行安裝依賴
npm install typescript ts-node
2.使用 ts-node 運行 ts 文件(這里使用 npx 來執(zhí)行 ts-node,因為 ts-node 是在本地項目中安裝的,如果直接使用的話會報命令找不到的錯誤,當(dāng)然如果在全局安裝了 ts-node npm 包就直接可以使用 ts-node 來運行,如果只是本地安裝了,那么需要加上 npx,這是會到 node_modules 文件夾中找到 ts-node 包來進(jìn)行執(zhí)行。)
全局安裝了: ts-node: ts-node xxx.ts
本地項目安裝了 ts-node: npx ts-node xxx.ts
補充: ts-node 也可以直接在命令行中編寫和執(zhí)行 ts 代碼,像 python 那樣,
如下圖:

2. tsc
tsc 顧名思義就是 typescript 的編譯器名稱,在安裝完 typescript 后,即可以使用 tsc 命令執(zhí)行 ts 文件,當(dāng)然不同于 ts-node 能夠直接運行 ts 文件,tsc 只是將 ts 文件編譯后輸出成 js 文件,然后可以再通過 node 來執(zhí)行生成的 js 文件。
tsc 有許多的配置項,當(dāng)運行 tsc --init 時可以在項目中生成 tsconfig.json 文件,這個文件里面包含了許多的配置,包括配置編譯后的文件輸出路徑,編譯后的文件用哪種模塊規(guī)范以及兼容 es6 語法等等選項。
//1.安裝 typescript npm install typescript //2.使用 tsc 生成 tsconfig.json 文件 npx tsc --init //3.使用 tsc 編譯 ts 文件 npx tsc xxx.ts
TypeScript 中的函數(shù)重載
TS 中的函數(shù)重載并不像其它語言中的函數(shù)重載一樣,和其它語言如 Java 比起來,更像是一種偽重載,它不能像 Java 中重載那樣實現(xiàn)同樣的函數(shù)名,但是參數(shù)個數(shù)不一樣,而是更多的為類型推斷服務(wù)。
簡單的排序算法
首先,使用 TS 來實現(xiàn)一個快速排序函數(shù):
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))
}上面這段代碼是使用泛型實現(xiàn)的快速排序函數(shù),快速排序比冒泡排序的性能要好很多,基本思想就是分治(divide and conquer),簡單來說就是先選一個元素作為中間數(shù),然后分成兩部分,小于這個元素的部分,和大于這個元素部分,接著再使用遞歸分別進(jìn)行處理這兩部分,將排序任務(wù)分解到最小,然后再合并。
上面代碼中的快速排序方式,如果傳遞的是英文數(shù)組那就沒問題,但是如果傳遞的是中文數(shù)組,那就不能正常排序了,所以中文數(shù)組需要單獨進(jìn)行處理,使用下面的函數(shù):
2. 中文排序
// 通過正則表達(dá)式,判斷是否是中文數(shù)組
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')
})
}如果是中文數(shù)組,那么使用數(shù)組內(nèi)置的 sort 函數(shù)進(jìn)行排序。
接下來,如果需要將英文數(shù)組中的每一項進(jìn)行排序,則還需要單獨的函數(shù)進(jìn)行處理:
3. 字符串自排序
// 英文自排序
function strSelfSort(str: string): string {
const strArr = str.split('')
return quickSort(strArr).join('')
}實現(xiàn)英文字符串自排序就是先將字符串進(jìn)行 split 分割成字符數(shù)組,然后傳遞到之前寫的快速排序函數(shù)中,得到結(jié)果后再通過 join 函數(shù)拼接成字符串返回。
那么,接下來將上面的幾種排序功能整合成一個單獨的通用函數(shù):
4. 通過泛型整合幾種排序
// 通用的排序函數(shù)
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}`)
}通過上面的通用排序函數(shù)可以看出,在函數(shù)內(nèi)部通過排序傳遞的數(shù)據(jù)類型,如果是 string 則調(diào)用自排序,接著如果是數(shù)組的話,再判斷是否是中文數(shù)組,如果是,則調(diào)用中文數(shù)組排序函數(shù)進(jìn)行排序,不是的話就認(rèn)定為是英文數(shù)組,英文數(shù)組首先使用 map 函數(shù)遍歷,判斷數(shù)組中如果存在 string 類型就先調(diào)用字符串自排序函數(shù)進(jìn)行排序,否則就原樣返回,最后再通過快速排序函數(shù)進(jìn)行排序,這樣就完成了英文數(shù)組既每一項都排序了,整體數(shù)組也進(jìn)行了排序。
雖然上面的排序函數(shù)功能已經(jīng)比較完善了,但是有一點不太好的地方就是這個函數(shù)返回了一個聯(lián)合類型 T[] | string,這樣就會導(dǎo)致通過這個函數(shù)排序的結(jié)果不能確切的推斷出具體的類型,而只能是個聯(lián)合類型,那么我們也只能使用這個聯(lián)合類型里共有的方法提示,
如下圖:


這里簡單的調(diào)用了一下寫好的排序函數(shù),返回的結(jié)果類型竟然是:string | string[][] 的聯(lián)合類型,這樣的返回結(jié)果對于開發(fā)后續(xù)功能來說很不友好,那么接下來,就使用 TS 中的函數(shù)重載來完善一下上面的排序函數(shù):
5. 使用函數(shù)重載完善排序功能
// 使用函數(shù)重載重構(gòu)排序函數(shù)
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}`)
}關(guān)于 TS 的函數(shù)重載,就是只有一個實現(xiàn)的函數(shù),其余都是函數(shù)簽名,而且必須放在實現(xiàn)函數(shù)的上面,在調(diào)用這個函數(shù)的時候,只會顯示上面的函數(shù)簽名函數(shù),而不會展示具體實現(xiàn)的函數(shù),但是實際執(zhí)行的卻是那個實現(xiàn)函數(shù),在這種情況下,通過使用函數(shù)重載寫個兩個不同參數(shù)和返回值的函數(shù)簽名提供給調(diào)用者使用,而在具體實現(xiàn)函數(shù)中去兼容處理,這樣做的好處就是調(diào)用者得到的返回值類型可以是某個具體的類型了,而不再是個聯(lián)合類型,更有益于后面的開發(fā)。
總結(jié)
通過使用 TS 的函數(shù)重載解決了當(dāng)一個函數(shù)返回一個聯(lián)合類型時,類型推斷不確定的問題,在某些會返回聯(lián)合類型的場景下可以嘗試使用,方便后續(xù)的類型推斷操作,所以說,TS 的一切真的都是為類型而服務(wù)的,怎么寫好 TS 代碼其實就是在更好的完善類型推斷,類型系統(tǒng)的過程,只有更好更準(zhǔn)確的類型推斷,才能發(fā)揮 TS 的作用,讓編譯器在開發(fā)過程中智能的告訴開發(fā)者有哪些屬性和方法可以調(diào)用,并且在調(diào)用了錯誤的屬性和方法后可以及時提醒開發(fā)者。
到此這篇關(guān)于TypeScript 泛型重載函數(shù)的使用方式的文章就介紹到這了,更多相關(guān)TypeScript 泛型重載函數(shù) 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用base64對圖片的二進(jìn)制進(jìn)行編碼并用ajax進(jìn)行顯示
這篇文章主要介紹了使用base64對圖片的二進(jìn)制進(jìn)行編碼并用ajax進(jìn)行顯示的相關(guān)資料,需要的朋友可以參考下2017-01-01

