TypeScript中的類型聲明文件的使用實(shí)戰(zhàn)場(chǎng)景
前言
在TypeScript(以下簡(jiǎn)稱TS)的學(xué)習(xí)和實(shí)戰(zhàn)中,類型聲明文件(.d.ts)是一個(gè)貫穿入門到進(jìn)階的核心知識(shí)點(diǎn)。它不僅能解決“類型缺失”導(dǎo)致的開(kāi)發(fā)提示異常、編譯報(bào)錯(cuò),更能讓我們?cè)谑褂玫谌絁S庫(kù)時(shí),享受TS帶來(lái)的類型校驗(yàn)和智能提示,是前端工程化、規(guī)范化開(kāi)發(fā)中不可或缺的一環(huán)。
本文將從“是什么、為什么用、怎么用”三個(gè)維度,結(jié)合實(shí)戰(zhàn)場(chǎng)景,帶你徹底搞懂TS類型聲明文件,幫你在前端進(jìn)階之路上再進(jìn)一步。
一、什么是類型聲明文件
在前面的代碼中,我們說(shuō)從 typescript 編譯到 Javascript 的過(guò)程中,類型消失了,比如下面的代碼:
const str = "hello";
type User = {
id: number
name: string
show?: (id: number, name: string) => void
}
const u:User = {
id:1,
name:"張三",
show(id,name){
console.log(id,name)
}
}
const users:Array<User> = [
{id:1,name:"jack"},
{id:2,name:"rose"}
]
function addUser(u:User){
// todos...
return true;
}
addUser(u);編譯成javascript之后:
"use strict";
const str = "hello";
const u = {
id: 1,
name: "張三",
show(id, name) {
console.log(id, name);
}
};
const users = [
{ id: 1, name: "jack" },
{ id: 2, name: "rose" }
];
function addUser(u) {
// todos...
return true;
}
addUser(u);但是是真的消失了嗎?其實(shí)并不是,如果大家留意之前我們?cè)?a rel="external nofollow" target="_blank">Playground上編寫(xiě)代碼,專門有一項(xiàng)就叫做DTS
你會(huì)發(fā)現(xiàn),我們寫(xiě)的代碼都自動(dòng)轉(zhuǎn)換成了typescript類型聲明。
當(dāng)然,這在我們的VS Code編輯器中也能生成的。只需要在tsconfig.json文件中加上相關(guān)配置即可
{
"compilerOptions": {
"target": "es2020",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"outDir": "./dist",
+ "declaration": true,
+ "declarationDir": "./types",
},
"include": ["src/**/*.ts"],
"exclude": ["./node_modules", "./dist", "./types"]
}運(yùn)行tsc,最后生成:[文件名].d.ts
declare const str = "hello";
type User = {
id: number;
name: string;
show?: (id: number, name: string) => void;
};
declare const u: User;
declare const users: Array<User>;
declare function addUser(u: User): boolean;也就是說(shuō),類型并不是真的全部消失了,而是被放到了專門的類型聲明文件里。
.d.ts結(jié)尾的文件,就是類型聲明文件。d的含義就是declaration
其實(shí)typescript本身就包含兩種文件類型
.ts文件:既包含類型信息,又包含可執(zhí)行代碼,可以被編譯成.js文件后執(zhí)行,主要是我們編寫(xiě)文件代碼的地方.d.ts文件:只包含類型信息的類型聲明文件,不會(huì)被編譯成.js代碼,僅僅提供類型信息,所以類型文件的用途就是提供類型信息
二、類型聲明文件的來(lái)源
類型聲明文件主要有以下三種來(lái)源
- TypeScript 編譯器自動(dòng)生成。
- TypeScript 內(nèi)置類型文件。
- 外部模塊的類型聲明文件,需要自己安裝。
三、如何自動(dòng)生成類型聲明文件
只要使用編譯選項(xiàng)declaration,編譯器就會(huì)在編譯時(shí)自動(dòng)生成單獨(dú)的類型聲明文件。
下面是在tsconfig.json文件里面,打開(kāi)這個(gè)選項(xiàng)。
{
"compilerOptions": {
"declaration": true
}
}declaration這個(gè)屬性還與其他屬性有強(qiáng)關(guān)聯(lián):
- declarationDir:指定生成的聲明文件d.ts的輸出目錄
- emitDeclarationOnly:只輸出 d.ts 文件,不輸出 JavaScript 文件
- declarationMap:為 d.ts 文件創(chuàng)建源映射
四、內(nèi)置聲明文件
安裝 TypeScript 語(yǔ)言時(shí),會(huì)同時(shí)安裝一些內(nèi)置的類型聲明文件,主要是內(nèi)置的全局對(duì)象(JavaScript 語(yǔ)言接口和運(yùn)行環(huán)境 API)的類型聲明。這也就是為什么string,number等等基礎(chǔ)類型,Javascript的api直接就有類型提示的原因
內(nèi)置聲明文件位于 TypeScript 語(yǔ)言安裝目錄的lib文件夾內(nèi)

這些內(nèi)置聲明文件的文件名統(tǒng)一為lib.[description].d.ts的形式,其中description部分描述了文件內(nèi)容。比如,lib.dom.d.ts這個(gè)文件就描述了 DOM 結(jié)構(gòu)的類型。
如果想了解對(duì)應(yīng)的全局對(duì)象類型接口,可以去查看這些內(nèi)置聲明文件。
tsconfig.json中的配置target和lib其實(shí)就和內(nèi)置聲明文件是有關(guān)系的。TypeScript 編譯器會(huì)自動(dòng)根據(jù)編譯目標(biāo)target的值,加載對(duì)應(yīng)的內(nèi)置聲明文件,默認(rèn)不需要特別的配置。我們也可以指定加載哪些內(nèi)置聲明文件,自定義配置lib屬性即可:
"lib":["es2020","dom","dom.iterable"]
為什么我們沒(méi)有安裝typescript之前也有提示?
這是由于我們的VS Code等IDE工具在安裝或者更新的時(shí)候,已經(jīng)內(nèi)置了typescript的lib。一般在你的VS Code安裝路徑 -> resources -> app -> extensios -> node_modules -> typescript 下
如果你的VS Code一直沒(méi)有升級(jí),就有可能導(dǎo)致本地VS Code的typescript版本跟不上的情況,如果你的項(xiàng)目目錄下,也安裝的的有typescript,我們是可以進(jìn)行切換的。
在VS Code中使用快捷鍵ctrl(command) + shift + P,輸入TypeScript

選擇Select Typescript Version…

你可以選擇使用VS Code版本還是項(xiàng)目工作區(qū)的版本
五、外部類型聲明文件
如果項(xiàng)目中使用了外部的某個(gè)第三方庫(kù),那么就需要這個(gè)庫(kù)的類型聲明文件。這時(shí)又分成三種情況了。
- 第三方庫(kù)自帶了類型聲明文件
- 社區(qū)制作的類型聲明文件
- 沒(méi)有類型聲明文件
沒(méi)有類型聲明這個(gè)很容易理解,我們現(xiàn)在不糾結(jié)這種情況,而且大多數(shù)情況下,我們也不應(yīng)該去糾結(jié)他,關(guān)鍵是1,2兩點(diǎn)是什么意思?其實(shí)我們下載兩個(gè)常用的第三方庫(kù)就能很明顯的看出問(wèn)題。
npm i axios lodash
注意:引入模塊之前,涉及到模塊的查找方式,因此在tsconfig.json中需要配置module
對(duì)于現(xiàn)代 Node.js 項(xiàng)目,我們可以配置NodeNext,注意這個(gè)配置會(huì)影響下面的配置:
"moduleResolution": "NodeNext", "esModuleInterop": true
當(dāng)然,具體模塊化的配置,不同的環(huán)境要求是不一樣的,有一定的區(qū)別,比如是nodejs環(huán)境,還是webpack的打包環(huán)境,或者說(shuō)是在寫(xiě)一個(gè)第三方庫(kù)的環(huán)境,對(duì)于模塊化的要求是不一樣的。而且還涉及到模塊化解析方式等問(wèn)題。這里就先不詳細(xì)深入講解了
在nodejs環(huán)境下,我們先簡(jiǎn)單配置為"module":"NodeNext"
在webapck/vite等打包環(huán)境下,設(shè)置為:
"module": "ESNext" "moduleResolution": "bundler"
引入相關(guān)模塊:

其實(shí)打開(kāi)這兩個(gè)庫(kù)的源代碼就能發(fā)現(xiàn)問(wèn)題,axios是有 .d.ts 文件的,而lodash沒(méi)有,也就是說(shuō)根本沒(méi)有類型聲明,那當(dāng)然就和提示的錯(cuò)誤一樣,無(wú)法找到模塊的聲明文件。
第三方庫(kù)如果沒(méi)有提供類型聲明文件,社區(qū)往往會(huì)提供。TypeScript 社區(qū)主要使用 DefinitelyTyped,各種類型聲明文件都會(huì)提交到那里,已經(jīng)包含了幾千個(gè)第三方庫(kù)。上面代碼提示的錯(cuò)誤,其實(shí)就是讓我們到@types名稱空間去下載lodash對(duì)應(yīng)的類型聲明,如果存在的話。當(dāng)然,你也可以到npm上進(jìn)行搜索。幾乎你知道的所有較大的庫(kù),都會(huì)在上面找到,所以一般來(lái)說(shuō)也要下載或者搜索都比較簡(jiǎn)單,@types開(kāi)頭,/后面加上第三方庫(kù)原來(lái)的名字即可,比如:@types/lodash,@types/jquery,@types/node,@types/react,@types/react-dom等等
npm i --save-dev @types/lodash
import lodash from 'lodash' const result = lodash.add(1, 2); console.log(result)

默認(rèn)情況下,所有可見(jiàn)的“@types”包都會(huì)包含在你的編譯中。任何包含文件夾中node_modules/@types的包都被視為可見(jiàn)。“任何包含文件夾”意味著不僅是項(xiàng)目的直接node_modules/@types目錄會(huì)被搜索,上層目錄中的相應(yīng)文件夾也會(huì)被遞歸搜索。
可以通過(guò)typeRoots選項(xiàng)設(shè)置查找的文件路徑,如果指定了typeRoots,則只會(huì)包含typeRoots下的包。例如:
{
"compilerOptions": {
"typeRoots": ["./typings", "./vendor/types"]
}
}這個(gè)配置文件將會(huì)包含./typings和./vendor/types下的所有包,但不會(huì)包含./node_modules/@types下的任何包。所有路徑都是相對(duì)于tsconfig.json文件的。
也就是說(shuō),如果你要手動(dòng)指定typeRoots,那就需要自己手動(dòng)指定所有需要查找的目錄,如果你的項(xiàng)目中有深層次的目錄結(jié)構(gòu),并且你希望包含其中的類型聲明,你需要確保這些目錄都被明確地添加到typeRoots中。
其實(shí),nodejs本身也沒(méi)有TypeScript的類型聲明,因此你會(huì)發(fā)現(xiàn)在.ts文件中直接引入nodejs相關(guān)的模塊同樣會(huì)報(bào)錯(cuò)
import path from "path"; // error 找不到模塊"path"或其相應(yīng)的類型聲明
同樣,我們直接在DefinitelyTyped下載即可
npm i @types/node -D
我們自己當(dāng)然也能編寫(xiě)類型聲明文件,但是聲明文件.d.ts大多數(shù)時(shí)候是第三方庫(kù)一起使用的,我們寫(xiě)代碼教學(xué)階段在nodejs環(huán)境下,單獨(dú)去聲明.d.ts文件沒(méi)有太大的意義,首先大家要知道這個(gè)問(wèn)題。所以,要使用.d.ts聲明文件的場(chǎng)景一般是:
- 自己寫(xiě)了一個(gè)主要是Javascript代碼的第三方庫(kù),需要給這寫(xiě)Javascript代碼加上類型聲明,以便用戶使用的時(shí)候可以得到類型聲明,方便調(diào)用API。
- 自己下載了別人寫(xiě)的第三方庫(kù),但是沒(méi)有typescript類型聲明,在社區(qū) DefinitelyTyped中也沒(méi)有找到對(duì)應(yīng)的類型聲明,但是我們一定要用這個(gè)庫(kù),可以手動(dòng)為這個(gè)庫(kù)添加一些簡(jiǎn)單的類型聲明,以免我們自己項(xiàng)目在使用這個(gè)第三方庫(kù)沒(méi)有類型聲明報(bào)出錯(cuò)誤提示。
- 在做應(yīng)用項(xiàng)目的時(shí)候,需要補(bǔ)充一些全局的類型聲明的時(shí)候,我們可能需要自己動(dòng)手寫(xiě).d.ts文件,其實(shí)這種情況大多數(shù)還是和第2點(diǎn)有關(guān)系
到此這篇關(guān)于TypeScript中的類型聲明文件的文章就介紹到這了,更多相關(guān)TypeScript類型聲明文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript分水嶺CommonJS對(duì)比ES模塊分析
這篇文章主要為大家介紹了JavaScript分水嶺CommonJS對(duì)比ES模塊分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
JS實(shí)現(xiàn)顏色梯度與漸變效果完整實(shí)例
這篇文章主要介紹了JS實(shí)現(xiàn)顏色梯度與漸變效果,結(jié)合完整實(shí)例形式分析了js顏色漸變所涉及的數(shù)學(xué)運(yùn)算與頁(yè)面樣式動(dòng)態(tài)操作相關(guān)技巧,需要的朋友可以參考下2016-12-12
Bootstrap table 定制提示語(yǔ)的加載過(guò)程
bootstrap-table是在bootstrap-table的基礎(chǔ)上寫(xiě)出來(lái)的,專門用于顯示數(shù)據(jù)的表格插件。這篇文章主要介紹了Bootstrap table 定制提示語(yǔ),需要的朋友可以參考下2017-02-02
JS實(shí)現(xiàn)Enter鍵跳轉(zhuǎn)及控件獲得焦點(diǎn)
想讓Enter鍵跳轉(zhuǎn)的同時(shí)讓控件獲得焦點(diǎn),具體實(shí)現(xiàn)js代碼如下,感興趣的朋友可以參考下,希望對(duì)大家有所幫助2013-08-08
解讀TypeScript與JavaScript的區(qū)別
這篇文章主要介紹了TypeScript與JavaScript的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
微信小程序?qū)崿F(xiàn)經(jīng)典window掃雷游戲
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)經(jīng)典window掃雷游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09
javascript實(shí)現(xiàn)3D切換焦點(diǎn)圖
一款用JavaScript模仿3D立體切換效果的js焦點(diǎn)幻燈片特效,使用方法很簡(jiǎn)單:用鼠標(biāo)拖拽圖片向左右方向就好~2015-10-10

