上帝視角看 TypeScript,充電了!
TypeScript 的學(xué)習(xí)資料非常多,其中也不乏很多優(yōu)秀的文章和教程。但是目前為止沒有一個(gè)我特別滿意的。原因有:
它們大多數(shù)沒有一個(gè)清晰的主線,而是按照 API 組織章節(jié)的,內(nèi)容在邏輯上比較零散。 大多是“講是什么,怎么用“,而不是”講為什么,講原理“。 大多數(shù)內(nèi)容比較枯燥,趣味性比較低。都是干巴巴的文字,沒有圖片,缺乏能夠引起強(qiáng)烈共鳴的例子。
因此我的想法是做一套不同市面上大多數(shù)的 TypeScript 學(xué)習(xí)教程。以人類認(rèn)知的角度思考問題,學(xué)習(xí) TypeScript,通過通俗易懂的例子和圖片來幫助大家建立 TypeScript 世界觀。而本篇文章則是這個(gè)系列的開篇。
注意,我的系列文章基本不會(huì)講 API,因此需要你有一定的 TypeScript 使用基礎(chǔ),推薦兩個(gè)學(xué)習(xí)資料。
深入理解 TypeScript??https://jkchao.github.io/typescript-book-chinese/ 官方文檔?https://www.typescriptlang.org/docs/home
結(jié)合這兩個(gè)資料和我的系列教程,掌握 TypeScript 指日可待。
接下來,我們通過幾個(gè)方面來從宏觀的角度來看一下 TypeScript。
從輸入輸出上來看
如果我們把 Typescript 編譯器看成一個(gè)黑盒的話。其輸入則是使用 TypeScript 語法書寫的文本或者文本集合。

(文本)
如果幾個(gè)文本有引用關(guān)系,比如 a.ts 依賴 foo.ts 和 bar.ts,其就是一個(gè)文本集合。

(文本集合)
輸出是編譯之后的 JS 文件 和 .d.ts 的聲明文件。

其中 JS 是將來需要運(yùn)行的文件,而 .d.ts 聲明文件則是 ts 文件中的類型聲明,這個(gè)類型聲明就是你在 ts 文件中聲明的類型和 TypeScript 類型推導(dǎo)系統(tǒng)推導(dǎo)的類型。當(dāng)然你也可以自己寫 .d.ts 聲明文件。
從功能上來看
從宏觀的視角來看,TypeScript 的功能就是:
提供了豐富的類型系統(tǒng)。
最簡單的就是 變量名:類型 = 值
const?a:?Number?=?1;
除了這些基本類型,還提供了函數(shù)類型,復(fù)合類型等。
提供了類型操作 API。TypeScript 不但提供內(nèi)置類型,用戶也可以利用集合操作和泛型對類型操作從而生成新的類型。

對每一種類型的屬性和方法都進(jìn)行了定義。
比如 String 類型有 toString 方法,但是沒有 toFixed 方法,這就是 lib.d.ts 定義的。這樣我在 String 類型的變量上使用 toFixed 方法就會(huì)報(bào)錯(cuò),達(dá)到了“類型檢查”的作用。
小提示:lib.d.ts 的內(nèi)容主要是一些變量聲明(如:window、document、math)和一些類似的接口聲明(如:Window、Document、Math)。你可以通過 --noLib 來關(guān)閉這一功能
提供了模塊系統(tǒng)(module,namespace)。 提供了更加方面的 API,比如 class(這在 ES6 class 出來之前尤其好用),裝飾器等。 。。。
TypeScript 編譯器是如何工作的?
上面已經(jīng)討論了 TypeScript 編譯器的輸入和輸出。那黑盒內(nèi)部是怎么工作呢?這里我簡單介紹一下:

TypeScript 文本首先會(huì)被解析為 token 流。這個(gè)過程比較簡單,就是單純地按照分隔符去分割文本即可。

接著 token 流會(huì)被轉(zhuǎn)換為 AST,也就是抽象語法樹。

binder 則根據(jù) AST 信息生成 Symbol(TypeScript 中的一個(gè)數(shù)據(jù)結(jié)構(gòu))。拿上面的圖來說,就是 number 節(jié)點(diǎn)。 當(dāng)我們需要類型檢查的時(shí)候, checker 會(huì)根據(jù)前面生成的 AST 和 symbols 生成類型檢查結(jié)果。 當(dāng)我們需要生成 JS 文件的時(shí)候,emitter 同樣會(huì)根據(jù)前面生成的 AST 和 symbols 生成 JS 文件。
完整圖:

總結(jié)
總的來說,TypeScript 就是一門語言,和 Java,Python,C++ 等類似。只不過這門語言主要目標(biāo)就是為了彌補(bǔ) JavaScript 弱類型帶來的問題的。因此設(shè)計(jì)語言的出發(fā)點(diǎn)就是:
靜態(tài)類型系統(tǒng) 可以編譯成 JavaScript
因此 TypeScript 是一門最終編譯為 JavaScript 的語言(當(dāng)然還有類型文件)。既然是一門語言,就涉及詞法分析,語法分析等流程。由于相對 JavaScript 增加了很多功能, 其中最主要的就是類型系統(tǒng)。因此 TypeScript 的分析工作要比 JavaScript 更加復(fù)雜, 集中體現(xiàn)在 binder 和 checker 部分。
由于提供了靜態(tài)類型, 因此就需要提供一些內(nèi)置類型給我們用,比如 number,string,Array 等。但是這并不能滿足我們的所有需求,我們需要自定義類型,因此有了 type,有了 interface 等。后來我們又發(fā)現(xiàn)自定義的類型重復(fù)代碼太多, 要是類型也可以通過編程生成新的類型就好了,于是有了集合運(yùn)算和泛型。
代碼都放到一起不方便維護(hù),要是可以放到不同文件,需要用的時(shí)候組裝起來就好了,于是有了模塊化。我用了別人的用 TypeScript 開發(fā)的庫,如果也能有類型校驗(yàn)就好了,于是有了 types。
。。。
其實(shí)這些都是有因果關(guān)系的,如果你可以牢牢地掌握這些因果關(guān)系,那么學(xué)起來還不是易如反掌?
相關(guān)閱讀
TypeScript 編譯原理?https://jkchao.github.io/typescript-book-chinese/compiler/overview.html Bring your own TypeScript with more internal definitions?https://github.com/basarat/byots Compiler Internals?https://github.com/microsoft/TypeScript/wiki/Compiler-Internals TypeScript 編譯器是用 TypeScript 寫的,那是先有編譯器還是 TS?https://github.com/azl397985856/fe-interview/issues/135
最后
如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個(gè)小忙:
點(diǎn)個(gè)「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點(diǎn)在看,都是耍流氓 -_-)
歡迎加我微信「qianyu443033099」拉你進(jìn)技術(shù)群,長期交流學(xué)習(xí)...
關(guān)注公眾號(hào)「前端下午茶」,持續(xù)為你推送精選好文,也可以加我為好友,隨時(shí)聊騷。

