停止使用 .d.ts 文件—如果你想讓你的應(yīng)用變慢 | 高級(jí) TypeScript

TypeScript 自推出以來(lái)已經(jīng)走了很長(zhǎng)一段路,現(xiàn)已成為為 JavaScript 添加類(lèi)型安全的首選工具。
無(wú)論你是經(jīng)驗(yàn)豐富的 TypeScript 老手,還是剛剛?cè)腴T(mén)的初學(xué)者,你可能都遇到過(guò) .d.ts 文件——這些神秘的類(lèi)型聲明文件似乎有自己獨(dú)立的世界。
在這篇文章中,我們將深入探討為什么在 2024 年我們需要使用 .d.ts 文件,它們?nèi)绾稳谌胛覀兊拈_(kāi)發(fā)流程,以及什么時(shí)候你可能更愿意堅(jiān)持使用一般的 .ts 文件。
為什么在 2024 年需要使用 .d.ts 文件
從高層次上看,.d.ts 文件是 TypeScript 聲明文件。它們包含類(lèi)型聲明(接口、類(lèi)型、類(lèi)等),但不包含任何實(shí)現(xiàn)代碼。
可以將它們看作是定義代碼結(jié)構(gòu)的藍(lán)圖,但并不實(shí)際構(gòu)建任何東西。
這些文件允許 TypeScript 理解你的模塊、類(lèi)和函數(shù)的形狀,而無(wú)需了解它們的底層邏輯。
什么是 .d.ts 文件?
那么,為什么在 .ts 文件中已經(jīng)可以直接定義類(lèi)型和接口時(shí),我們還需要這些 .d.ts 文件呢?
答案在于 TypeScript 如何與 JavaScript 生態(tài)系統(tǒng)和外部庫(kù)進(jìn)行接口設(shè)計(jì)。
.d.ts 文件的作用
- 關(guān)注點(diǎn)分離使用 .d.ts 文件的一個(gè)關(guān)鍵原因是保持類(lèi)型定義和實(shí)現(xiàn)代碼之間的清晰分離。這在處理大型代碼庫(kù)或開(kāi)發(fā)供他人使用的庫(kù)時(shí)尤為有用。通過(guò)將類(lèi)型隔離在 .d.ts 文件中,你可以保持實(shí)現(xiàn)的清晰和專(zhuān)注,同時(shí)讓他人更容易理解你的模塊的 API 表面。
示例:
通過(guò) .d.ts 文件,干凈地將契約與實(shí)現(xiàn)分開(kāi)。 

- 庫(kù)開(kāi)發(fā)如果你正在開(kāi)發(fā)一個(gè)供其他 TypeScript 或 JavaScript 項(xiàng)目使用的庫(kù),.d.ts 文件是不可或缺的。它們?cè)试S你公開(kāi)一個(gè)定義良好的 API,而不會(huì)泄露實(shí)現(xiàn)細(xì)節(jié)。當(dāng)他人安裝你的庫(kù)時(shí),得益于這些聲明文件,他們可以在使用時(shí)獲得完整的 IntelliSense 支持和類(lèi)型安全。
在發(fā)布庫(kù)時(shí),將 .d.ts 文件包含在你的包中,可以讓使用者獲得類(lèi)型信息,而無(wú)需轉(zhuǎn)譯你的代碼或深入研究實(shí)現(xiàn)。 - 第三方庫(kù)集成通常,我們會(huì)使用并非用 TypeScript 編寫(xiě)的 JavaScript 庫(kù)。為了利用 TypeScript 的類(lèi)型檢查,我們需要描述這些庫(kù)提供的對(duì)象和函數(shù)的形狀。這時(shí) .d.ts 文件就派上了用場(chǎng)。許多流行的庫(kù),如 jQuery 或 Lodash,都有在 DefinitelyTyped 倉(cāng)庫(kù)中維護(hù)的社區(qū)版本的 .d.ts 文件,可以通過(guò) npm 安裝。
示例: 

一旦安裝,TypeScript 即可對(duì) Lodash 的使用進(jìn)行類(lèi)型檢查,盡管 Lodash 本身不是用 TypeScript 編寫(xiě)的。
- 大型項(xiàng)目中的性能提升在大型項(xiàng)目中,將類(lèi)型定義放在 .d.ts 文件中可以幫助提高性能。TypeScript 的編譯器可以比普通 .ts 文件更快地分析這些文件,因?yàn)?.d.ts 文件不包含實(shí)際的實(shí)現(xiàn)代碼。它們只描述類(lèi)型,從而簡(jiǎn)化了編譯過(guò)程。
 
何時(shí)使用 .d.ts 文件而不是普通 .ts 文件
盡管 .d.ts 文件非常有用,但它們并不總是最佳選擇。
有時(shí),將類(lèi)型和接口直接存儲(chǔ)在 .ts 文件中更為合理,尤其是在你正在處理一個(gè)內(nèi)部項(xiàng)目時(shí),分離實(shí)現(xiàn)和類(lèi)型并不那么重要。
在以下情況下使用 .d.ts 文件:
- 開(kāi)發(fā)庫(kù):如前所述,如果你的代碼將被他人使用,使用 .d.ts 文件來(lái)公開(kāi)一個(gè)干凈的 API 是最佳實(shí)踐。
 - 與 JavaScript 庫(kù)進(jìn)行接口對(duì)接:當(dāng)你需要描述第三方 JavaScript 庫(kù)提供的類(lèi)型時(shí)。
 - 隔離類(lèi)型定義:如果你希望通過(guò)將類(lèi)型與實(shí)現(xiàn)分離來(lái)保持項(xiàng)目的組織,尤其是在大型項(xiàng)目中或類(lèi)型在許多模塊中復(fù)用時(shí)。
 
在以下情況下堅(jiān)持使用 .ts 文件:
- 內(nèi)部項(xiàng)目:如果你的項(xiàng)目是內(nèi)部使用的,并且不需要單獨(dú)公開(kāi)類(lèi)型,保持所有內(nèi)容在 .ts 文件中可能更簡(jiǎn)單。
 - 小型項(xiàng)目:在小型項(xiàng)目中,維護(hù)單獨(dú)的 .d.ts 文件的開(kāi)銷(xiāo)可能不值得。
 - 快速原型開(kāi)發(fā):當(dāng)你在項(xiàng)目中快速迭代時(shí),將類(lèi)型與實(shí)現(xiàn)放在同一文件中可以避免上下文切換,從而更快。
 
2024 年使用 .d.ts 文件的最佳實(shí)踐 ??
- 利用 TypeScript 的 declare 關(guān)鍵字在編寫(xiě) .d.ts 文件時(shí),記住你不需要使用export關(guān)鍵字,除非你在處理模塊。相反,使用declare表示類(lèi)型和接口是全局可用的。
示例: 
declare interface MyInterface {
  name: string;
  age: number;
}- 保持 .d.ts 文件的簡(jiǎn)潔.d.ts 文件的美妙之處在于其簡(jiǎn)潔性。它們只應(yīng)包含類(lèi)型聲明——?jiǎng)e無(wú)其他。避免在這些文件中包含邏輯或初始化代碼的誘惑。
 - 謹(jǐn)慎使用 /// <reference /> 指令雖然可以使用 /// <reference /> 指令鏈接 .d.ts 文件,但盡量避免,除非絕對(duì)必要。相反,依賴(lài) TypeScript 的模塊解析來(lái)管理類(lèi)型文件之間的依賴(lài)關(guān)系。
 - 邏輯地組織類(lèi)型聲明按照與你項(xiàng)目架構(gòu)相匹配的方式組織 .d.ts 文件。例如,將全局類(lèi)型放在一個(gè) globals.d.ts 文件中,將模塊特定的類(lèi)型放在各自模塊目錄中的 .d.ts 文件中。
 
結(jié)論
在 2024 年,.d.ts 文件依然是 TypeScript 開(kāi)發(fā)者工具箱中的強(qiáng)大工具。
它們?yōu)榇笮晚?xiàng)目帶來(lái)了清晰性、組織性和性能優(yōu)勢(shì),在構(gòu)建 JavaScript 和 TypeScript 生態(tài)系統(tǒng)中的庫(kù)時(shí)更是不可或缺。
然而,像所有工具一樣,應(yīng)該謹(jǐn)慎且恰當(dāng)?shù)厥褂盟鼈?。通過(guò)理解何時(shí)以及如何使用 .d.ts 文件,你可以編寫(xiě)更清晰、可維護(hù)性更強(qiáng)的代碼,并為自己和他人創(chuàng)造更好的開(kāi)發(fā)體驗(yàn)。
所以,下次你在設(shè)計(jì)一個(gè) TypeScript 項(xiàng)目時(shí),不妨考慮一下 .d.ts 文件是否應(yīng)該出現(xiàn)在你的代碼庫(kù)中。它們很可能會(huì)讓你的生活——以及代碼——變得更好。















 
 
 














 
 
 
 