TypeScript 配置文件該怎么寫(xiě)?
點(diǎn)擊藍(lán)色“腦洞前端”關(guān)注我喲
加個(gè)“星標(biāo)”,帶你揭開(kāi)大前端的神秘面紗!
?這是腦洞前端第「104」篇原創(chuàng)文章
TypeScript 的學(xué)習(xí)資料非常多,其中也不乏很多優(yōu)秀的文章和教程。但是目前為止沒(méi)有一個(gè)我特別滿(mǎn)意的。原因有:
它們大多數(shù)沒(méi)有一個(gè)清晰的主線(xiàn),而是按照 API 組織章節(jié)的,內(nèi)容在「邏輯上」比較零散。 大多是“講是什么,怎么用“,而不是”講為什么,講原理“。 大多數(shù)內(nèi)容比較枯燥,趣味性比較低。都是干巴巴的文字,沒(méi)有圖片,缺乏能夠引起強(qiáng)烈共鳴的例子。
因此我的想法是做一套不同市面上大多數(shù)的 TypeScript 學(xué)習(xí)教程。以人類(lèi)認(rèn)知的角度思考問(wèn)題,學(xué)習(xí) TypeScript,通過(guò)通俗易懂的例子和圖片來(lái)幫助大家建立 TypeScript 世界觀。
系列安排:
上帝視角看 TypeScript TypeScript 類(lèi)型系統(tǒng) types 和 @types 是什么? TypeScript 配置文件該怎么寫(xiě)?(就是本文) TypeScript 是如何與 React,Vue,Webpack 集成的? TypeScript 練習(xí)題
?目錄將來(lái)可能會(huì)有所調(diào)整。
?
注意,我的系列文章基本不會(huì)講 API,因此需要你有一定的 TypeScript 使用基礎(chǔ),推薦兩個(gè)學(xué)習(xí)資料。
深入理解 TypeScript?https://jkchao.github.io/typescript-book-chinese/ 官方文檔?https://www.typescriptlang.org/docs/home
結(jié)合這兩個(gè)資料和我的系列教程,掌握 TypeScript 指日可待。
接下來(lái),我們通過(guò)幾個(gè)方面來(lái)從宏觀的角度來(lái)看一下 TypeScript。
前言
這篇文章是我的 TypeScript 系列的「第 5 篇」。今天我們就來(lái)看下, TypeScript 的配置文件 tsconfig.json 該如何寫(xiě)。
和 package.json 一樣, 它也是一個(gè) JSON 文件。package.json 是包描述文件,對(duì)應(yīng)的 Commonjs 規(guī)范,而 「tsconfig.json 是最終被 TypeScript Compiler 解析和使用的一個(gè) JSON 文件」。TypeScript Compiler 用這個(gè)配置文件來(lái)決定如何對(duì)項(xiàng)目進(jìn)行編譯。
說(shuō)到編譯,不得不提一個(gè)知名選手 - babel。和 TypeScript 類(lèi)似, 他們都可以將一種語(yǔ)法靜態(tài)編譯成另外一種語(yǔ)法。如果說(shuō)我想編譯一個(gè)文件,我只需要告訴 babel 我的文件路徑即可。
npx?babel?script.js
有時(shí)候我想編譯整個(gè)文件夾:
npx?babel?src?--out-dir?lib
babel 也可以指定輸出目錄,指定需要忽略的文件或目錄等等, TypeScript 也是一樣!你當(dāng)然可以像 babel 一樣在命令行中全部指定好,也可以將這些配置放到 tsconfig.json 中,以配置文件的形式傳遞給 TypeScript Compiler 。這就是 tsconfig.json 文件的初衷,即接受用戶(hù)輸入作為配置項(xiàng)。
初探 tsconfig
我們先來(lái)看一個(gè)簡(jiǎn)單的 tsconfig 文件。
{
??"compilerOptions":?{
????"outDir":?"./built",
????"allowJs":?true,
????"target":?"es5"
??},
??"include":?["./src/**/*"]
}
如上配置做了:
讀取所有可識(shí)別的 src 目錄下的文件(通過(guò) include)。 接受 JavaScript 做為輸入(通過(guò) allowJs)。 生成的所有文件放在 built 目錄下(通過(guò) outDir)。 將 JavaScript 代碼降級(jí)到低版本比如 ECMAScript 5(通過(guò) target)。
實(shí)際項(xiàng)目有比這個(gè)更復(fù)雜。接下來(lái), 我們來(lái)進(jìn)一步解讀。不過(guò)在講配置項(xiàng)之前,我們先來(lái)看下 tsconfig.json 是如何被解析的。
tsconfig 是如何被解析的?
「如果一個(gè)目錄下存在一個(gè) tsconfig.json 文件,那么意味著這個(gè)目錄是 TypeScript 項(xiàng)目的根目錄。」 如果你使用 tsc 編譯你的項(xiàng)目,并且沒(méi)有顯式地指定配置文件的路徑,那么 tsc 則會(huì)逐級(jí)向上搜索父目錄尋找 tsconfig.json ,這個(gè)過(guò)程類(lèi)似 node 的模塊查找機(jī)制。

如圖:
在 [email protected]@uglify-js 下執(zhí)行 tsc 則會(huì)找到 配置文件 1,在 [email protected]@uglify-js/bin 下執(zhí)行 tsc 也會(huì)找到 配置文件 1 同理在 lib,node_modules 也會(huì)找到 配置文件 1 在 [email protected]@uglify-js/bin/lucifer 下執(zhí)行 tsc 則會(huì)找到 配置文件 2 在 [email protected]@uglify-js/lib/lucifer 下執(zhí)行 tsc 則會(huì)找到 配置文件 3
我在 上帝視角看 TypeScript 一種講述了 TypeScript 究竟做了什么,帶你從宏觀的角度看了一下 TypeScript。其中提到了 TypeScript 編譯器會(huì)接受文件或者文件集合作為輸入,最終轉(zhuǎn)換為 JavaScript(noEmit 為 false) 和 .d.ts(declarations 為 true)。

這里其實(shí)還少了一個(gè)點(diǎn),那就是除了接受文件或者文件集合作為輸入,還會(huì)接受 tsconfig.json。tsconfig.json 的內(nèi)容決定了編譯的范圍和行為,不同的 配置可能會(huì)得到不同的輸出,或者得到不同的檢查結(jié)果。
當(dāng) tsc 找到了一個(gè) tsconfig.json 文件,那么其規(guī)定的編譯目錄則全部會(huì)被 typescript 處理,當(dāng)然也包括其依賴(lài)的文件。如果 tsc 沒(méi)有找到一個(gè) tsconfig.json 或 tsconfig 沒(méi)有有效信息,那么 tsc 會(huì)使用默認(rèn)配置。比如 tsconfig 是一個(gè)空的就沒(méi)有有效信息:
{}
?tsconfig 的全部屬性,以及屬性的默認(rèn)值可以在這里找到:http://json.schemastore.org/tsconfig
?
總結(jié)一下 tsc 解析 tsconfig.json 的邏輯。
如果命令行指定了配置選項(xiàng)或者指定了配置文件的路徑,那么直接會(huì)讀取。 如果正確,則將其和默認(rèn)配置合并(如果有 extends 字段,也會(huì)一起合并),將合并后的配置傳遞給 TypeScript 編譯器并開(kāi)始編譯。 否則拋出錯(cuò)誤 根據(jù) tsconfig json schema 校驗(yàn)是否格式正確。 否則,會(huì)從當(dāng)前目錄查找 tsconfig.json 文件, 如果找不到則逐層向上搜索父目錄。 如果正確,則將其和默認(rèn)配置合并(如果有 extends 字段,也會(huì)一起合并),將合并后的配置傳遞給 TypeScript 編譯器并開(kāi)始編譯。 否則拋出錯(cuò)誤 如果找到了則會(huì)去根據(jù) tsconfig json schema 校驗(yàn)是否格式正確。 否則,始終找不到則直接使用默認(rèn)配置
tsconfig 的頂層屬性
tsconfig 的頂層屬性(Top Level)不多,主要有:「compilerOptions, files, include, exclude,extends,compileOnSave」等。
compilerOptions 是重頭戲,其屬性也是最多的,我們的項(xiàng)目也是對(duì)這個(gè)定制比較多,這個(gè)我后面會(huì)重點(diǎn)講。 files 則是你需要編譯的文件 exclude 則是你不需要編譯的文件目錄(支持 glob) include 是你需要編譯的文件目錄(支持 glob) extends 就是繼承另外一個(gè)配置文件,TypeScript 會(huì)對(duì)其進(jìn)行合并,多項(xiàng)目公共配置有用。你也可以直接繼承社區(qū)的“最佳實(shí)踐”,比如:
{
??"extends":?"@tsconfig/node12/tsconfig.json",
??"compilerOptions":?{},
??"include":?["src/**/*"],
??"exclude":?["node_modules"]
}
compileOnSave 則是和編輯器(確切地說(shuō)是文件系統(tǒng))聯(lián)動(dòng)的配置,即是否在文件保存后進(jìn)行編譯,實(shí)際項(xiàng)目不建議使用。
除了 compilerOptions,其他也相對(duì)比較好理解。因此接下來(lái)我只針對(duì) compilerOptions 詳細(xì)講解一番。
tsconfig 的編譯項(xiàng)
詳細(xì)全面的內(nèi)容,大家只需要參考官網(wǎng)[1]的就好了。官網(wǎng)寫(xiě)的不僅全面,而且做了分類(lèi),非常清晰。
接下來(lái),我會(huì)根據(jù)功能分開(kāi)講幾個(gè)「常用」 的配置。
文件相關(guān)
常用的是以下四個(gè),由于前面已經(jīng)做了介紹,因此就不贅述了。
exclude extends files include
嚴(yán)格檢查
alwaysStrict
默認(rèn):false
首次發(fā)布版本:2.1
這個(gè)是和 ECMAScript 規(guī)范相關(guān)的,工作機(jī)制和 ES 5 的嚴(yán)格模式一樣, 并且輸出的 JS 頂部也會(huì)也會(huì)帶上 'use strict'。
noImplicitAny(推薦打開(kāi))
默認(rèn):true
首次發(fā)布版本:-
我在 - TypeScript 類(lèi)型系統(tǒng) 中提到了如果不對(duì)變量顯式聲明類(lèi)型,那么 TypeScript 會(huì)對(duì)變量進(jìn)行類(lèi)型推導(dǎo),這當(dāng)然也有推導(dǎo)不出的情況,這個(gè)時(shí)候該變量的類(lèi)型就是 any,這個(gè)叫做隱式 any。區(qū)別于顯式 any:
const?a:?any?=?{};
隱式 any 是 TypeScript 編譯器推斷的。
noImplicitThis(推薦打開(kāi))
默認(rèn):true
首次發(fā)布版本:2.0
和隱式 any 類(lèi)型, 只不過(guò)這次是針對(duì)的特殊的一個(gè)關(guān)鍵字 this,也就是你需要顯式地指定 this 的類(lèi)型。
strict(推薦打開(kāi))
默認(rèn):true
首次發(fā)布版本:2.3
實(shí)際上 strict 只是一個(gè)簡(jiǎn)寫(xiě),是多個(gè)規(guī)則的合集。類(lèi)似于 babel 中插件(plugins)和 預(yù)設(shè)(presets)的差別。換句話(huà)說(shuō)如果你指定了 strict 為 true ,那么所有嚴(yán)格相關(guān)的規(guī)則的都會(huì)開(kāi)啟,我所講的「嚴(yán)格檢查」都是,還有一部分我沒(méi)有提到的。另外將來(lái)如果增加更多嚴(yán)格規(guī)則,你只要開(kāi)啟了 strict 則會(huì)自動(dòng)加進(jìn)來(lái)。
模塊解析
模塊相關(guān)
目的:「allowSyntheticDefaultImports,allowUmdGlobalAccess,esModuleInterop,moduleResolution 都是為了和其他模塊化規(guī)范兼容做的。」
allowSyntheticDefaultImports allowUmdGlobalAccess esModuleInterop moduleResolution
還有一個(gè)配置 「module」,規(guī)定了項(xiàng)目的模塊化方式,選項(xiàng)有 AMD,UMD,commonjs 等。
路徑相關(guān)
目的:「baseUrl,paths,rootDirs, typeRoots,types 都是為了簡(jiǎn)化路徑的拼寫(xiě)做的。」
baseUrl
這個(gè)配置是告訴 TypeScript 如何解析模塊路徑的。比如:
import?{?helloWorld?}?from?"hello/world";
console.log(helloWorld);
這個(gè)就會(huì)從 baseUrl 下找 hello 目錄下的 world 文件。
paths
定義類(lèi)似別名的存在,從而簡(jiǎn)化路徑的書(shū)寫(xiě)。
rootDirs
注意是 rootDirs ,而不是 rootDir,也就是說(shuō)根目錄可以有多個(gè)。當(dāng)你指定了多個(gè)根目錄的時(shí)候, 不同根目錄的文件可以像在一個(gè)目錄下一樣互相訪(fǎng)問(wèn)。
?實(shí)際上也有一個(gè)叫 rootDir 的, 和 rootDirs 的區(qū)別就是其只能指定一個(gè)。
?
typeRoots types
types 和 typeRoots 我在 - types 和 @types 是什么?已經(jīng)講得很清楚了,這里就不多說(shuō)了。
項(xiàng)目配置
JavaScript 相關(guān)
allowJs
默認(rèn):false
首次發(fā)布版本:1.8
顧名思義,允許在 TypeScript 項(xiàng)目中使用 JavaScript,這在從 JavaScript 遷移到 TypeScript 中是非常重要的。
checkJs
默認(rèn):false
首次發(fā)布版本:-
和 allowJs 類(lèi)似, 只不過(guò) checkJs 會(huì)額外對(duì) JS 文件進(jìn)行校驗(yàn)。
聲明文件相關(guān)
如果 TypeScript 是將 TS 文件編譯為 JS,那么聲明文件 + JS 文件就可以反推出 TS 文件。
這兩個(gè)用來(lái)生成 .d.ts 和 .d.ts 的 sourcemap 文件。
declaration
默認(rèn):false
首次發(fā)布版本:1.0
declarationMap
默認(rèn):false
首次發(fā)布版本:2.9
外部庫(kù)相關(guān)
jsx
默認(rèn):react
首次發(fā)布版本:2.2
這個(gè)是告訴 TypeScript 如何編譯 jsx 語(yǔ)法的。
lib
默認(rèn):-
首次發(fā)布版本:2.0
lib 我在 TypeScript 類(lèi)型系統(tǒng) 中講過(guò)。Typescript 提供了諸如 lib.d.ts 等類(lèi)型庫(kù)文件。隨著 ES 的不斷更新, JavaScript 類(lèi)型和全局變量會(huì)逐漸變多。Typescript 也是采用這種 lib 的方式來(lái)解決的。

(TypeScript 提供的部分 lib)
輸出相關(guān)
outDir 和 outFile 這兩個(gè)配置則是告訴 TypeScript 將文件生成到哪里。
outDir
默認(rèn):和 ts 文件同目錄(且同名,只是后綴不同)
首次發(fā)布版本:-
outFile
默認(rèn):-
首次發(fā)布版本:1.0
module 是 CommonJS 和 ES6 module 不能知道 outFile,只有是 None, System 或 AMD 才行,其會(huì)將這些模塊的文件內(nèi)容打包到全局文件內(nèi)容之后。
而 noEmit 則是控制是否輸出 JS 文件的。
noEmit
默認(rèn):false
首次發(fā)布版本:-
如果你只希望用 TypeScript 進(jìn)行類(lèi)型檢查,不希望要它生成文件,則可以將 noEmit 設(shè)置成 true。
target
即輸出的 JavaScript 對(duì)標(biāo)的 ECMA 規(guī)范。比如 “target”: “es6” 就是將 es6 + 的語(yǔ)法轉(zhuǎn)換為 ES6 的 代碼。其選項(xiàng)有 ES3,ES5,ES6 等。
?為什么沒(méi)有 ES4 ?^_^
?
總結(jié)
tsconfig 就是一個(gè) JSON 文件,TypeScript 會(huì)使用該文件來(lái)決定如何編譯和檢查 TypeScript 項(xiàng)目。和 babel 類(lèi)似,甚至很多配置項(xiàng)都是相通的。
如果一個(gè)目錄下存在一個(gè) tsconfig.json 文件,那么意味著這個(gè)目錄是 TypeScript 項(xiàng)目的根目錄。如果你使用 tsc 編譯你的項(xiàng)目,并且沒(méi)有顯式地指定配置文件的路徑,那么 tsc 則會(huì)逐級(jí)向上搜索父目錄尋找 tsconfig.json ,這個(gè)過(guò)程類(lèi)似 node 的模塊查找機(jī)制。
tsconfig 中最重要的恐怕就是編譯器選項(xiàng)(compilerOptions)了。如果你按照功能去記憶則會(huì)比較簡(jiǎn)單, 比如文件相關(guān)的有哪些, 嚴(yán)格檢查的有哪些,聲明文件的有哪些等等。
參考
typescriptlang's tsconfig?https://www.typescriptlang.org/tsconfig
Reference
官網(wǎng)-tsconfig: https://www.typescriptlang.org/tsconfig
??看完三件事
如果你覺(jué)得這篇內(nèi)容對(duì)你挺有啟發(fā),我想邀請(qǐng)你幫我三個(gè)小忙:
點(diǎn)贊,讓更多的人也能看到介紹內(nèi)容(收藏不點(diǎn)贊,都是耍流氓-_-) 關(guān)注公眾號(hào)“前端勸退師”,不定期分享原創(chuàng)知識(shí)。 也看看其他文章
勸退師個(gè)人微信:huab119
也可以來(lái)我的GitHub博客里拿所有文章的源文件:
前端勸退指南:https://github.com/roger-hiro/BlogFN一起玩耍呀
在看、點(diǎn)贊、轉(zhuǎn)發(fā)支持作者??
