ts自动编译声明文件_拥抱 TS:细数选择 TS 的 N 种理由
作者 | 馬靖
day day up, bye bye bug
最近在做一個新項目,技術大佬告知前端要用 TS 。前端小白的我內心疑惑“弱類型語言它不香嘛,為什么選擇 TS ?” 為了緊隨大佬的流星大步,擁抱變化。帶著這個疑惑我積(被)極(破)主(營)動(業)點開了谷歌,開始了地毯式的搜索。
1、TS 的前世今生
1.1 背景故事
2010 年微軟公司的一個深夜,擁有黑眼圈的程序員們加班改 bug ,其中一個資深程序員抱怨“這聲明的變量不寫類型注釋,還偷偷改數據類型,寫的人也太不靠譜,這維護難搞哦”。正巧被路過的老板聽見,第二天微軟決定以該程序員為首,成立一個緊急小組開發一門新語言TypeScript,需求是提升大型 JS 項目的可靠性和可維護性。TS 從 2010 年開始研發后一直作為微軟的內部項目使用,直到 2012 年,發布了第一個公開版本【 TypeScript 0.8 版 】后,受到前端程序員的激烈推崇點贊,紛紛學習使用。自此 TS 就開始了漫漫迭代之路,時至今日仍然大受歡迎。
1.2 TS 是什么
這個故事告訴我們 TS 存在的目的,是為了提升大型 JS 項目的可靠性和可維護性。那 TS 到底是什么?官方定義來了 TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open source. 翻譯過來:TypeScript 是 JavaScript 的一個超集,可以編譯為純 JavaScript ,在任何瀏覽器、集群(服務器)、操作系統上面都可以運行,而且還開源。一張圖來了解它的大小。?
前端程序員:開發工具用 VScode;包管理用 npm;代碼用 TS;社區用 GitHub。一家人就是要整整齊齊(瀏覽器就算了)。我們可以將 TypeScript 看作是 JavaScript 之上的一個外殼,擁有類型的 JavaScript ;TS = Type + Javascript。看到這里不禁有疑惑,它到底做了什么能成為 JS 超集,既然可編譯為 JS 又是怎么提升大型 JS 項目可靠性和可維護性的呢?
1.3 TS 做了什么
擴展 JS 數據類型
TS 中數據類型:boolean 類型、 number 類型、 string 類型、 Object 類、 function 類、 array 類型、 undefined、 null、 Symbol、 tuple 類型(元組類型)、 enum 類型(枚舉類型)、 any 類型(任意類型)、 void 類型(沒有任何類型)、 never 類型(永不存在的值的類型) TS 還提供了 as 類型斷言, 強制類型轉換。如果這些還不能表達出你想要的數據類型,想要組合型結構,為難我 TS ?它來了,它來了,它帶著接口走來了。
接口
在面向對象編程中,接口是一種規范的定義,它定義行為和動作的規范。TS 的核心原則之一是對值所具有的結構進行類型檢查。它有時被稱做“鴨式辨型法”或“結構性子類型化”。在 TS 里,接口的作用就是為這些類型命名和為你的代碼或第三方代碼定義契約。其實在程序設計里面,接口起到一定的限制和規范作用。接口定義對象里的屬性和方法所遵守的規范。如果非要形象貼近生活一點的話,那接口就像是充電口,你是什么類型的充電口,就必須要用這個類型的充電器。你定義什么類型的接口,那你必須使用相同類型的數據。TS 的接口增加了更靈活的接口類型,包括屬性,函數,索引和類等。TS 中的接口不僅可以約束,相同接口還可以合并同”名“項。了解到的和常用的接口如下:1. 屬性類接口,對屬性值的類型定義;2. 參數約束接口,規定調用方法的傳參類型,避免出現數據類型不一致導致 JS 直接卡死在瀏覽器的語法錯誤;3. 參數修飾,可選類型、必選類型和限制接口中的參數是只讀類型等;4. 泛型接口,增強了接口的可復用性;5. 函數接口,規定函數參數值類型以及返回值類型,避免出現空返回值導致中止程序的現象;6. 索引簽名,可以添加不確定參數名稱的屬性;7. 類接口,對類的約束,和抽象類有點像;8. 接口擴展,如果你聲明了兩個接口名一樣的接口,那么 TS 會對該接口進行合并操作;9. 使用 type 別名 可提取自定義聯合類型;10. 接口做閉包,主要是混合類型,當一個函數有自己的屬性和方法;
提供類型系統、類型推論和靜態檢查
如果是在支持 TS 的 IDE 中( VS Code、WebStorm 等),則不需等到編譯,編碼時 IDE 就可以非常明顯在 localCompare 位置提示出錯誤信息。非空判斷 開發中有時會直接引用某個對象的屬性,但有時候該屬性的數據格式有可能為空,這種場景在前端處理后端接口返回值時經常出現。有時候數據層級可能非常深,如果在某一級缺少了非空判斷邏輯,意味著埋下了一個不知道什么時候就會引爆的炸彈。而 TS 會對屬性進行非空判斷。想舉個栗子證實?在聲明變量的時候一旦指定變量的數據類型,后續使用到該變量的時候 TS 會進行靜態數據類型分析檢查,即使編寫的代碼即使沒有被執行到,依舊進行檢查。如果發現類型不匹配,在編譯階段(解釋執行也一樣,可以在運行前)就會直接報紅報錯,但只是報紅并不影響它編譯為 JS ,也就是說就算是有靜態類型檢查報錯的文件,編譯之后代碼仍可運行。
報錯: Subsequent property declarations must have the same type. Property 'x' must be of type 'number', but here has type 'string'.
覺得太正經,就不想中規中矩?如果使用變量的時候沒有指定數據類型,后續使用時是不是就逃過靜態類型檢查了呢?答案是 No ,在 TS 里,沒有明確指出類型的地方,類型推論會幫助提供類型。如果是聲明式,類型推論是發生在初始化變量和成員,設置默認參數值和決定函數返回值時進行的;如果沒有聲明,比如參數,TS 類型推論也可能按照相反的方向進行,按上下文歸類,上下文歸類會與表達式的類型與所處的位置關聯起來,進行類型推斷。別想了,你是逃不掉強檢查的~?
優點:1,編譯期出現不可靠代碼立即報紅提示,降低純 JS 開發風險;2,類型即為最好的文檔注釋,人與機器雙懂,降低多人開發的溝通成本,豈不三全其美。
泛型
最初了解到泛型,是在大學時期學習 C# 時,老師介紹:“允許延遲編寫類或方法中的編程元素的數據類型的規范,直到實際在程序中使用它的時候。泛型允許編寫一個可以與任何數據類型一起工作的類或方法。可以通過數據類型的替代參數編寫類或方法的規范。當編譯器遇到類的構造函數或方法的函數調用時,它會生成代碼來處理指定的數據類型。編譯器無答復,運行期才會根據需要生成。“ 在軟件工程中,我們在創建一致的定義良好的 API ,同時也要考慮重用性。讓組件不僅能夠支持當前的數據類型,還能支持未來的數據類型。初聞不知曲中意,再聽已是曲終人。當初不聽老師言,如今主動去鉆研!應景!其實在 C# 和 Java 強語言中,可使用泛型來創建可重用的組件,一個組件支持多種類型的數據。以自己的數據類型來使用組件。TS 也支持泛型,泛型只用于表示數據類型而非數值。泛型會捕獲傳入的數據類型,并定義該類型,在后續使用到泛型的地方,數據類型需要使用已經定義的泛型。泛型主要是解決類、接口、方法的復用性以及支持不定類型的數據。如下代碼。function identity(arg: T): T { return arg; //如果你傳入的 arg 參數為 number 類型,那么 T 就為 number }
IDE 智能提示
TS 完美解決了 IDE/編輯器 無法智能提示的痛點,敲代碼的時候不用記太多屬性,類型之類的內容。TS 會自動提示屬性和類型等內容。來,看圖?
面向對象編程增強
TS 新增訪問權限控制:public:共有,類的成員屬性/方法默認都是 public,沒有訪問限制;private:私有,無法在該類聲明的外部訪問其成員(如無法通過 this.xxx 訪問私有成員);protected:與 private 類似,但在派生類中也可以訪問受保護成員。
TS 還引入了類,聲明合并、模塊、模塊解析、支持 TSX 等等。自己發現了解吧。手動放入 TS 官網
2、TS 與 JS 的愛恨交織
通過上面簡要介紹,我們知道 TS 作為 JS 的語法糖,TS 將 JS 更加具體化類型化,在編譯過程中對數據類型和代碼設計更加規范也更有層次感。TS 支持 ES 標準,擴展 JS 語法,TS 原則之一永遠和 ES 規范保持一致。TS 在編譯時作為靜態類型檢查的弱類型語言,但編譯后運行時是動態類型的弱語言 ,只在編譯時強檢查,符合 TS 設計原則,“不給編譯產物增加運行時開銷”。
愛與恨
既然 TS 編譯后依然是 JS ,那為什么前端程序員不喜歡老東家 JS 呢?聊聊我的拙見。
首先,要從 JS 的設計初衷來說。JS 定義時作為一門動態類型的弱類型語言,沒有固定的數據類型,使用非常靈活。小插曲,記憶深處有次知識分享前端大佬騷操作猛如虎,后端小哥看完震驚 “原來寫代碼還可以這么隨意,跟玩的一樣”。動態類型的弱類型語言沒有固定的數據結構,隨時可更改數據類型,確實很靈活,正所謂動態類型一時爽,代碼重構火葬場。靈活的語言有一個弊端就是沒有固定數據類型,你定義什么我就執行什么,這就導致多人開發時亂賦值的現象。TS 設計原則之一是“實現一種可組合、易推理的( easy to reason about )語言”。提供類型化 + 靜態類型檢查 + 類型推斷,來靜態識別出那些可能會出錯的代碼,符合 TS 設計原則,“在編碼階段就扼制不安全代碼的產生”。
其次,JS 的設計只有 10 天時間,最初只是一個輔助 Java 的腳本語言,小打小鬧的 JS 沒想成大氣候,奈何太受歡迎一不小心成了名,缺少一些構建大型應用的特性,比如接口、結構化、類等等。JS 有苦說不出,沒關系,TS 哥哥來幫忙。TS 提供接口,泛型等一切為大型 JS 項目所需要的東西。
交織
介紹這么多,TS 彌補 JS 不足,那 TS 與 JS 在開發之外的層面,是不是只有首字母的不同呢?
語言規范
JS 和 TS 都是 ECMAScript(即 ES 規范)的具體實現。TS 的設計原則之一“永遠和 ES 規范保持一致“。也就是 JS 的新規范新特性,都可在 TS 中直接書寫。在語言規范層面,JS 與 TS 確實只是首字母的不同。
運行環境
瀏覽器引擎和 Node.js 都能夠直接運行 JS,但無法直接運行 TS。可以用它來編寫面向對象的服務端或客戶端程序,需要將它們編譯成 JS 代碼后執行了。
時序執行
As we all know.瀏覽器只寵 JS + HTML + CSS 集團。TS 是不能直接在被瀏覽器識別,TS 被真正執行前,會通過編譯轉換生成 JS,之后才能被解釋執行。TS 可編譯成 JS 代碼,也就是說開發中的 JS 代碼,在 TS 中依然有效可用,符合 TS 的設計原則,“輸出整潔、地道、可讀的 JS 代碼”。
家境背書
JS 由 Netscape 率先推出,現在主要由各大瀏覽器廠商實現。而 TS,TypeScript is a trademark of Microsoft Corporation,目前由微軟進行設計和維護。
重構維護
長期迭代維護的項目開發和維護的成員會有很多,長期迭代維護的項目總會遇到可維護性逐漸降低的問題,有了強類型約束和靜態檢查,以及智能 IDE 的幫助下,可以降低軟件腐化的速度,提升可維護性,且在重構時,強類型和靜態類型檢查會幫上大忙,甚至擁有類型定義,會不經意間增加重構的頻率(更安全、放心)。當然了,重構還是要看具體業務,切莫為了滿足個人愛好,從而給整個團隊帶來額外的成本。
開發效率
雖然需要多寫一些類型定義代碼,但 TS 在 VSCode、WebStorm 等 IDE 下可以做到智能提示,智能感知 bug,同時我們項目常用的一些第三方類庫框架都有 TS 類型聲明,我們也可以給那些沒有 TS 類型聲明的穩定模塊寫聲明文件,這在團隊協作項目中可以提升整體的開發效率。
3、總結
TS 適合大規模 JS 項目( JavaScript that scales )。TS 在團隊協作、可維護性、易讀性、可靠性(編譯期暴露問題)等方面上有著明顯的優點:1. 加上了類型系統,對人好,對機器好,對維護也很好,無形中增強了代碼的雙層可讀性;對于編譯階段來說,類型定義在編譯期可揪出隱藏的 bug,健壯性強;2. 類型系統 + 靜態分析檢查 + 智能感知提示,書寫方便,使大規模的應用代碼質量更高, bug 少,維護方便,就連重構也安心;3. 給應用配置、應用狀態、前后端接口及各種模塊定義類型,使得整個應用由類型定義組成,可擴展,多人協作更為方便、高效和安全。
彩蛋:題目有彩蛋,你是否發現
全文完
以下文章您可能也會感興趣:
WePY 2.0 新特性
SSL證書的自動化管理
了解一下第三方登錄
分布式 ID 生成策略
單元測試的實踐之路
可線性化檢查:與 NP 完全問題做斗爭
Java 類型系統從入門到放棄
Webpack 快速上手(下)
Webpack 快速上手(中)
Webpack 快速上手(上)
我們正在招聘 Java 工程師,歡迎有興趣的同學投遞簡歷到 rd-hr@xingren.com 。
總結
以上是生活随笔為你收集整理的ts自动编译声明文件_拥抱 TS:细数选择 TS 的 N 种理由的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flask基础知识总结
- 下一篇: Django模板(编写html代码