有些簡單的Typescript配置,可讓你得到更快的編譯和編輯體驗,這些方法越早掌握越好。下面列舉了除了最佳實踐之外,還有一些用於調查緩慢的編譯/編輯體驗的經常使用技術,以及一些做爲最後手段來幫助TypeScript團隊調查問題的經常使用方法。html
不少時候,簡單對象類型的類型別名與接口的做用很是類似node
然而,只要你須要定義兩個及以上的類型,你就能夠選用接口來擴展這些類型,或者在類型別名中對它們相交,這時差別就變得明顯了。webpack
因爲接口定義的是單一平面對象類型,能夠檢測屬性是否衝突,解決這些衝突是很是必要的。另外一方面,交叉類型只是遞歸的合併屬性,有些狀況下會產生never。接口則表現的一向很好,而交叉類型定義的類型別名不能顯示在其餘的交叉類型上。接口之間的類型關係也會被緩存,而不是整個交叉類型。最後值得注意的區別是,若是是交叉類型,會在檢查「有效」 /「展平」類型以前檢查全部屬性。git
所以,建議在建立交叉類型時使用帶有接口/擴展的擴展類型。web
添加類型註釋,尤爲是返回類型,能夠節省編譯器的大量工做。這是由於命名類型比匿名類型更簡潔(編譯器更喜歡),這減小了大量的讀寫聲明文件的時間。雖然類型推導是很是方便的,沒有必要處處這麼作。可是,若是您知道了代碼的慢速部分,可能會頗有用。typescript
聯合類型很是好用--它可讓你表達一種類型的可能值範圍。json
可是他們也帶來了必定開銷。每次將參數傳遞給 printSchedule
時,須要比較聯合類型裏的每一個元素。對於一個由兩個元素組成的聯合類型來講,這是微不足道的。可是,若是你的聯合類型有不少元素,這將引發編譯速度的問題。例如,從聯合類型中淘汰多餘的部分,元素須要成對的去比較,工做量是呈二次遞增的。當大量聯合類型交叉一塊兒時發生這種檢查,會在每一個聯合類型上相交致使大量的類型,須要減小這種狀況發生。避免這種狀況的一種方法是使用子類型,而不是聯合類型。gulp
一個更現實的例子是,定義每種內置DOM元素的類型時。這種狀況下,更優雅的方式是建立一個包含全部元素的 HtmlElement
基礎類型,其中包括 DivElement
、 ImgElement
等。使用繼承而不是建立一個無窮多的聯合類型 DivElement | /\*...\*/ | ImgElement | /\*...\*/
。緩存
使用TypeScript構建內容較多的代碼時,將代碼庫組織成幾個獨立的項目會頗有用。每一個項目都有本身的 tsconfig.json
,可能它會對其餘項目有依賴性。這有益於避免在一次編譯中導入太多文件,也使某些代碼庫佈局策略更容易地放在一塊兒。安全
有一些很是基本的方法將一個代碼庫分解成多個項目。舉個例子,一個程序代碼,一部分用做客戶端,一部分用做服務端,另外一部分被其它兩個共享
測試也能夠分解到本身的項目中
一個常見的問題是 "一個項目應該有多大?"。這很像問 "一個函數應該有多大?"或 "一個類應該有多大?",在很大程度上,這歸結於經驗。人們熟悉的一種分割JS/TS代碼的方法是使用文件夾。做爲一種啓發式的方法,若是它們關聯性足夠大,能夠放在同一個文件夾中,那麼它們就屬於同一個項目。除此以外,要避免出現極大或極小規模的項目。若是一個項目比其餘全部項目加起來都要大,那就是一個警告信號。一樣,最好避免有幾十個單文件項目,由於也會增長開銷。
TypeScript
和JavaScript
用戶能夠用tsconfig.json
文件任意配置編譯方式。JavaScript
用戶也可使用jsconfig.json
文件配置本身的編輯體驗。
你應該始終確保你的配置文件沒有包含太多文件
在 tsconfig.json
中,有兩種方式能夠指定項目中的文件
二者的主要區別是,files
指望獲得一個源文件的文件路徑列表,而include/exclude
使用通配符模式對文件進行匹配
雖然指定文件可讓TypeScript
直接快速地加載文件,但若是你的項目中有不少文件,而不僅是幾個頂層的入口,那就會很麻煩。此外,很容易忘記添加新文件到tsconfig.json
中,這意味着你可能最終會獲得奇怪的編輯器行爲,這些新文件被錯誤地分析,這些都很棘手。
include/exclude
有助於避免指定這些文件,但代價是:必須經過include
包含的目錄來發現文件。當運行大量的文件夾時,這可能會減慢編譯速度。此外,有時編譯會包含不少沒必要要的.d.ts
文件和測試文件,這會增長編譯時間和內存開銷。最後,雖然exclude
有一些合理的默認值,但某些配置好比mono-repos
,意味着像node_modules
這樣的 "重 "文件夾仍然能夠最終被包含。
對於最佳作法,咱們建議以下:
node_modules
注意:若是沒有排除列表,默認狀況下node_modules是被排除的;一旦添加了node_modules,就必須明確地將node_modules添加到列表中。
下面是一個合理的tsconfig.json
,用來演示這個操做
默認狀況下,TypeScript
會自動包含每個在node_modules
文件夾中找到的@types
包,無論你是否導入它。這是爲了在使用Node.js、Jasmine、Mocha、Chai等工具_包時,使某些東西 "可以工做",由於這些工具_包沒有被導入--它們只是被加載到全局環境中
有時這種邏輯在編譯和編輯場景下都會拖慢程序的構建時間,甚至會形成多個全局包的聲明衝突的問題,形成相似於以下問題
在不須要全局包的狀況下,修復方法很簡單,只要在 tsconfig.json/jsconfig.json
中爲 "type "選項指定一個空字段便可。
若是您仍然須要一些全局包,請將它們添加到類型字段中
--incremental
標誌容許TypeScript將上次編譯的狀態保存到一個 .tsbuildinfo
文件中。這個文件用來計算上次運行後可能被從新檢查/從新輸出的最小文件集,就像TypeScript的--watch
模式同樣。
當對項目引用使用複合標誌時,默認狀況下會啓用增量編譯,但這樣也能帶來一樣的速度提高。
默認狀況下,TypeScript會對一個項目中的全部.d.ts
文件進行全面檢查,以發現問題或不一致的地方;然而,這檢查一般是沒必要要的。大多數時候,.d.ts
文件都是已知如何工做的--類型之間相互擴展的方式已經被驗證過一次,重要的聲明仍是會被檢查。
TypeScript提供了一個選項,使用skipDefaultLibCheck
標誌來跳過.d.ts
文件的類型檢查(例如lib.d.ts
)
另外,你也能夠啓用 skipLibCheck
標誌來跳過編譯中的全部 .d.ts
文件
這兩個選項一般會隱藏.d.ts
文件中的錯誤配置和衝突,因此只建議在快速構建場景中使用它們。
狗的列表是動物的列表嗎?也就是說,List<Dog>
是否能夠分配給List<Animals>
?尋找答案的直接方法是逐個成員進行類型結構比較。不幸的是,這可能帶來昂貴的性能開銷。然而,若是咱們對List<T>
有足夠的瞭解,咱們能夠將這個可分配性檢查簡化爲肯定Dog,是否能夠分配給Animal(即不考慮List<T>
的每一個成員)。特別是,當咱們須要知道類型參數T的差異。編譯器只有在啓用strictFunctionTypes
標誌的狀況下,才能充分利用這種潛在的加速優點(不然,它就會使用較慢的,但更寬鬆的結構檢查)。所以,咱們建議使用 --strictFunctionTypes
來構建(默認在 --strict
下啓用)
TypeScript編譯常常與其餘構建工具一塊兒執行--特別是在編寫可能涉及捆綁程序的Web應用程序時。雖然咱們只能對一些構建工具提出建議,但理想狀況下,這些技術能夠被普及。
確保除了閱讀本節外,你還閱讀了關於你所選擇的構建工具的性能--例如:
類型檢查一般須要從其餘文件中獲取信息,與轉換_輸出代碼等其餘步驟相比,類型檢查可能相對昂貴。由於類型檢查可能會花費更多的時間,它可能會影響到內部的開發循環--換句話說,你可能會經歷更長的編輯_編譯/運行週期,這可能會令你頭疼。
出於這個緣由,一些構建工具能夠在一個單獨的進程中運行類型檢查,而不會阻塞輸出。雖然這意味着在TypeScript構建而發生錯誤報告以前已經有無效的代碼運行,一般會先在編輯器中看到錯誤,而不會被長時間地阻止運行工做代碼
一個實際的例子是Webpack的fork-ts-checker-webpack-plugin
插件,或者awesome-typescript-loader
有時也會這樣作。
默認狀況下,TypeScript輸出須要的語義信息可能不是本地文件。這是爲了理解如何輸出像 const enums
和 namespaces
這樣的功能。可是須要檢查其餘文件來生成某個文件,這會使輸出速度變慢。
對須要非本地信息的功能需求是比較少見的--常規枚舉能夠用來代替const
枚舉,模塊能夠用來代替命名空間。鑑於此,TypeScript提供了isolatedModules
標誌,以便在由非本地信息驅動的功能上報錯。啓用 isolatedModules
意味着你的代碼庫對於使用 TypeScript APIs
(如 transpileModule
)或替代編譯器(如 Babel
)的工具是安全的。
舉個例子,下面的代碼在運行時沒法正常使用獨立的文件轉換,由於const enum
值被指望內聯;幸運的是, isolatedModules
會在早期告訴咱們這一點
記住:isolatedModules不會自動讓代碼生成速度更快--它只是告訴你,你即將使用一個可能不被支持的功能。你要的是獨立模塊在不一樣的構建工具和API中的輸出
能夠經過使用如下工具來影響獨立文件的輸出
有必定的方法能夠獲得可能出問題的提示
編輯器的體驗受到插件的影響。嘗試禁用插件(尤爲是JavaScript/TypeScript相關的插件),看看是否能解決性能和響應速度方面的問題。
某些編輯器也有本身的性能故障排除指南,因此能夠考慮閱讀一下。例如,Visual Studio Code
也有本身的性能問題介紹。
你能夠用--extendedDiagnostics
來運行TypeScript,以得到編譯器花費時間的打印日誌。
請注意,總時間不是前面全部時間的總和,由於有一些重疊,有些工做是沒有衡量工具的。
對於大多數用戶來講,最相關的信息是:
考慮到這些投入,你可能會想問一些問題:
--listFiles
其餘時間看起來不對勁嗎?你可能想提出一個問題。你能夠作如下事情來幫助診斷
emitDeclarationOnly
運行當運行 tsc 時,並不能明顯地看到編譯的內容設置,特別是考慮到 tsconfig.jsons
能夠擴展其餘配置文件。showConfig
能夠解釋 tsc 將爲一個調用計算着什麼。
運行 traceResolution
能夠有助於解釋,一個文件爲何被包含在編譯中。輸出有點繁瑣,因此你可能想把輸出重定向到一個文件。
若是你發現了一個不該該存在的文件,你可能須要修改你的tsconfig.json中的include/exclude列表,或者,你可能須要調整其餘設置,好比type、typeRoots或paths。
不少時候,用戶在使用第三方構建工具(如Gulp、Rollup、Webpack等)時都會遇到性能緩慢的問題。運行tsc --extendedDiagnostics
,能夠發現TypeScript和工具之間的差別,用以說明外部配置的錯誤或效率低下。
一些須要注意的問題:
有時TypeScript的類型檢查會受到計算密集的.d.ts
文件的影響。這很罕見也極可能會發生。升級到一個較新的TypeScript版本(能夠更有效率)或一個較新版本的@types包(可能已經恢復了一個迴歸)一般能夠解決這個問題。
一旦你已經排除了故障,你可能想探索一些常見問題的修復方法。若是如下解決方案不起做用,可能值得提出問題。
如上所述,include/exclude選項能夠在如下幾個方面被濫用
若是你的項目已經進行了正確的優化配置,你可能須要提出一個問題。
最好的性能問題報告包含容易得到的和最小的問題複製品。換句話說,一個容易經過git克隆的代碼庫,只包含幾個文件。它們不須要與構建工具的外部集成--它們能夠經過調用tsc或調用TypeScript API的獨立代碼。不優先考慮那些須要複雜調用和設置的代碼庫。
咱們理解這一點卻不容易實現--特別是,很難在代碼庫中隔離問題的源頭,並且共享知識產權可能也是一個問題。在某些狀況下,若是咱們認爲問題影響較大,團隊將願意發送一份保密協議(NDA)。
不管是否能夠複製,在提交問題時,按照這些方法,將有助於爲您提供性能修復。
有時,你會在構建時間以及編輯場景中發現性能問題。在這種狀況下,最好關注於TypeScript編譯器。
首先,應該使用TypeScript的next版本,以確保你不會碰到那些已解決的問題。
一個編譯器的問題可能包括
經過使用--trace-ic
標誌與--generateCpuProfile
標誌,來讓TypeScript運行Node.js v10+,這對團隊提供診斷結果來講是很重要的:
這裏的 ._node_modules_typescript_lib_tsc.js 能夠用來替換你的TypeScript編譯器的安裝版本,而tsconfig.json能夠是任何TypeScript配置文件。 profile.cpuprofile是你選擇的輸出文件。
這將產生兩個文件:
--trace-ic
將輸出到 isolate-*-*-*.log 的文件中(例如 isolate-00000176DB2DF130-17676-v8.log)--generateCpuProfile
將以您選擇的名稱輸出到一個文件中。在上面的例子中,它將是一個名爲 profile.cpuprofile 的文件警告:這些文件可能包含你的工做空間的信息,包括文件路徑和源代碼。這兩個文件均可以做爲純文本閱讀,您能夠在將它們提交爲 GitHub 問題以前修改它們。(例如,清除可能暴露內部專用信息的文件路徑)。可是,若是你對在GitHub上公開發布這些有任何顧慮,請告訴咱們,能夠私下分享細節。
編輯性能常常受到不少東西的影響,TypeScript團隊惟一能控制的是JavaScript/TypeScript語言服務的性能,以及該語言服務和某些編輯器(即Visual Studio、Visual Studio Code、Visual Studio for Mac和Sublime Text)之間的集成。確保全部第三方插件在編輯器中被關閉,以肯定是否有TypeScript自己的問題。
編輯性能問題稍有涉及,但一樣的想法也適用於:可被克隆的最小重現代碼庫是理想的,雖然在某些狀況下,團隊將可以簽署NDA來調查和隔離問題。
包括tsc--extendedDiagnostics的輸出是很好的上下文,但取一個TSServer日誌是最有用的。
打開你的命令菜單欄,而後選擇
⚠警告:TSServer日誌可能會包含你的工做空間的信息,包括文件路徑和源代碼。若是你對在GitHub上公開發布有任何顧慮,請告訴咱們,你能夠私下分享細節。