同學(xué)你好,我是Lison。很高興你對(duì)TypeScript感興趣,或許你對(duì)TypeScript了解還不多,或許還有很多疑問(wèn),比如:
- 學(xué) TypeScript 是不是就不需要學(xué) JavaScript 了?
- Vue 用 TypeScript 改寫(xiě)發(fā)布 3.0 后是不是不用 TypeScript 不行?
- TypeScript 靠譜嗎?
- …
諸如此類(lèi)疑惑,導(dǎo)致你一直對(duì)它猶豫不決,那么本節(jié)我將代替 TypeScript 向你做一個(gè)自我介紹。
同學(xué)你好,我是 TypeScript,如果你覺(jué)得我是 JavaScript 的孿生兄弟,或者覺(jué)得我是前端圈新扶持起來(lái)的太子,那你可能對(duì)我是有點(diǎn)誤解了。其實(shí)我并不是一個(gè)新的語(yǔ)言,用大家公認(rèn)的說(shuō)法,我是JavaScript的超集,你可以理解為,我是加了一身裝備銘文的進(jìn)化版 JavaScript。JavaScript 有的,我都有,而且做得更好。JavaScript 沒(méi)有的,我也有,而且我是在很長(zhǎng)一段時(shí)間內(nèi)不會(huì)被 JavaScript 趕上的。
雖然我作為超集,但是我始終緊跟 ECMAScript 標(biāo)準(zhǔn),所以 ES6/7/8/9 等新語(yǔ)法標(biāo)準(zhǔn)我都是支持的,而且我還在語(yǔ)言層面上,對(duì)一些語(yǔ)法進(jìn)行拓展。比如新增了枚舉(Enum)這種在一些語(yǔ)言中常見(jiàn)的數(shù)據(jù)類(lèi)型,對(duì)類(lèi)(Class)實(shí)現(xiàn)了一些ES6標(biāo)準(zhǔn)中沒(méi)有確定的語(yǔ)法標(biāo)準(zhǔn)等等。
如果你是一個(gè)追趕技術(shù)潮流的開(kāi)發(fā)者,那你應(yīng)該已經(jīng)將 ES6/7/8/9 語(yǔ)法用于開(kāi)發(fā)中了。但是要想讓具有新特性的代碼順利運(yùn)行在非現(xiàn)代瀏覽器,需要借助Babel這種編譯工具,將代碼轉(zhuǎn)為ES3/5版本。而我,可以完全不用 Babel,就能將你的代碼編譯為指定版本標(biāo)準(zhǔn)的代碼。這一點(diǎn),我可以說(shuō)和 JavaScript 打了個(gè)平手。
另外我的優(yōu)勢(shì),想必你也略有耳聞了那就是我強(qiáng)大的類(lèi)型系統(tǒng)。這也是為什么造世主給我起名TypeScript。如果你是一名前端開(kāi)發(fā)者,或者使用過(guò) JavaScript 進(jìn)行開(kāi)發(fā),那么你應(yīng)該知道,JavaScript 是在運(yùn)行的時(shí)候,才能發(fā)現(xiàn)一些錯(cuò)誤的,比如:
- 訪(fǎng)問(wèn)了一個(gè)對(duì)象沒(méi)有的屬性;
- 調(diào)用一個(gè)函數(shù)卻少傳了參數(shù);
- 函數(shù)的返回值是個(gè)字符串你卻把它當(dāng)數(shù)值用了;
- …
這些問(wèn)題在我這里都不算事。我強(qiáng)大的類(lèi)型系統(tǒng)可以在你編寫(xiě)代碼的時(shí)候,就檢測(cè)出你的這些小粗心。先來(lái)簡(jiǎn)單看下我工作的樣子:
interface 定義的叫接口,它定義的是對(duì)結(jié)構(gòu)的描述。下面的 info 使用 ES6 的新關(guān)鍵字 const 定義,通過(guò) info: Info 指定 info 要實(shí)現(xiàn) Info 這個(gè)結(jié)構(gòu),那 info 必須要包含 name 和 age 這兩個(gè)字段。實(shí)際代碼中卻只有 name 字段,所以你可以看到 info 下面被紅色波浪線(xiàn)標(biāo)記了,說(shuō)明它有問(wèn)題。當(dāng)你把鼠標(biāo)放在 info 上時(shí),VSCode 編輯器會(huì)做出如下提示:

配合VSCode這類(lèi)編輯器,你可以借助編輯器的提示愉快地使用 TypeScript。另外值得一提的是,深受前端開(kāi)發(fā)者喜愛(ài)的 VSCode 也是使用 TypeScript 開(kāi)發(fā)的哦。
很多后端開(kāi)發(fā)者,在做了很久的后端開(kāi)發(fā),習(xí)慣了 C++、Java 這些語(yǔ)言后,可能對(duì)我會(huì)有很多誤解。就拿一個(gè)函數(shù)重載來(lái)說(shuō)吧,在別的這些語(yǔ)言里,你可以定義多個(gè)同名函數(shù),然后不同點(diǎn)在于參數(shù)個(gè)數(shù)、參數(shù)類(lèi)型和函數(shù)體等,你可以給同一個(gè)函數(shù)傳入不同參數(shù),編譯器就會(huì)知道你要調(diào)用的是哪個(gè)函數(shù)體;而我,也是有函數(shù)重載的概念的,只不過(guò),我的重載是為了幫助編譯器知道,你給同一個(gè)函數(shù)傳入不同參數(shù),返回值是什么情況;在 JavaScript 中,我們?nèi)绻幸粋€(gè)函數(shù),要根據(jù)傳入?yún)?shù)不同,執(zhí)行不同的邏輯,是需要自己在函數(shù)體內(nèi)自行判斷的。比如下面這個(gè)JavaScript 書(shū)寫(xiě)的例子:
const getResult = input => {
if (typeof input === 'string') return input.length
else if (typeof input === 'number') return input.toString()
else return input
}
這個(gè)例子很簡(jiǎn)單。如果輸入的值是字符串類(lèi)型,返回這個(gè)字符串的長(zhǎng)度;如果是數(shù)值類(lèi)型,返回這個(gè)數(shù)值變成字符串的結(jié)果;如果都不是,原樣返回??梢钥吹?,輸入不同類(lèi)型的值,返回的結(jié)果類(lèi)型是不一樣的。所以如果你要使用這個(gè)函數(shù)的返回值,就可能一不小心用錯(cuò),比如輸入123,應(yīng)該返回字符串 ‘123’。如果你在結(jié)果上調(diào)用 toFixed 方法,如 getResult(123).toFixed(),運(yùn)行后就會(huì)報(bào)錯(cuò),因?yàn)樽址菦](méi)有這個(gè)方法的。如果你使用我來(lái)書(shū)寫(xiě),結(jié)果就不同了,我會(huì)在你寫(xiě)代碼的時(shí)候就告訴你。來(lái)看怎么使用我來(lái)書(shū)寫(xiě)上面的例子:
function getResult (input: string): number
function getResult (input: number): string
function getResult <T>(input: T): T
function getResult (input: any): any {
if (typeof input === 'string') return input.length
else if (typeof input === 'number') return input.toString()
else return input
}
前三行組成了函數(shù)重載,第四行開(kāi)始是實(shí)際函數(shù)體,之后你再調(diào)用 getResult 來(lái)看下效果:

這里輸入字符串’abc’,返回應(yīng)該是他的長(zhǎng)度數(shù)值3,結(jié)果訪(fǎng)問(wèn)它的length屬性,數(shù)值是沒(méi)有l(wèi)ength屬性的。
這里你傳入一個(gè)對(duì)象,既不是字符串也不是數(shù)值,所以原樣返回這個(gè)對(duì)象,編譯器就知道你的res是對(duì)象 { a: ‘a(chǎn)’, b: ‘b’ } 啦。所以當(dāng)你輸入res然后輸入 . 后,VSCode 就會(huì)給你列出有哪些屬性可以訪(fǎng)問(wèn)。
是不是和你理解的函數(shù)重載有點(diǎn)不一樣?所以一定要注意哦,不要用學(xué)習(xí)其他語(yǔ)言的思維來(lái)認(rèn)識(shí)我哦,否則你會(huì)鉆牛角尖的。上面例子的語(yǔ)法你可以不用在意,因?yàn)?Lison 都會(huì)詳詳細(xì)細(xì)地給你講噠。
對(duì)了,另外還有一個(gè)我的好搭檔,TSLint,也是追求極致的你不可或缺的。它和 ESLint 相似,都是能夠?qū)δ愕拇a起到約束和提示作用,特別是團(tuán)隊(duì)協(xié)作的項(xiàng)目中,使用它可以讓你們多個(gè)開(kāi)發(fā)者都能夠遵循相同的代碼規(guī)范——大到各種語(yǔ)法,小到標(biāo)點(diǎn)空格。搭配使用 VSCode 和 TSLint,再加上我強(qiáng)大的類(lèi)型系統(tǒng),寫(xiě)代碼簡(jiǎn)直不要太嗨~
好了,向你介紹得差不多了,相信你對(duì)我已經(jīng)有了一個(gè)大致的了解。下面讓 Lison 向你客觀(guān)地介紹下,我的發(fā)展趨勢(shì)以及你為什么要與我為伴。
相信你在聽(tīng)完 TypeScript 的自我介紹之后,它的亮點(diǎn)你已經(jīng)了解一二了?;蛟S你還有些顧慮,畢竟學(xué)習(xí) TypeScript 是需要時(shí)間的,你可能會(huì)擔(dān)心 TypeScript 像 CoffeeScript 一樣,隨著 ES標(biāo)準(zhǔn) 的不斷更新,漸漸退出大家的視線(xiàn)。下面讓我們來(lái)看下 TypeScript 的發(fā)展趨勢(shì),來(lái)打消你的顧慮,同時(shí)讓你對(duì)它有進(jìn)一步的了解。
我們都知道 TypeScript 最主要的亮點(diǎn)是它的類(lèi)型系統(tǒng),這使得在編寫(xiě)代碼的時(shí)候就能夠檢測(cè)到一些錯(cuò)誤。而 JavaScript 是一門(mén)動(dòng)態(tài)腳本語(yǔ)言,它不需要編譯成二進(jìn)制代碼運(yùn)行。Node 服務(wù)端代碼也不需編譯即可在服務(wù)器起一個(gè)服務(wù),你甚至可以直接在服務(wù)器修改你的服務(wù)代碼然后重啟就可以,不需要編譯等操作。這一切特點(diǎn)使得 JavaScript 的所有調(diào)試都需要在運(yùn)行時(shí)才能進(jìn)行,在編寫(xiě)代碼的時(shí)候很多問(wèn)題是無(wú)法提前知曉的,而且就JavaScript目前的使用場(chǎng)景來(lái)看,它在至少很長(zhǎng)一段時(shí)間內(nèi)會(huì)保持這樣的特點(diǎn)。
而 TypeScript 和 JavaScript 不同的就是,它可以在你編寫(xiě)代碼的時(shí)候,就對(duì)一些錯(cuò)誤進(jìn)行提示,還能在你使用某個(gè)數(shù)據(jù)的時(shí)候,為你列出這個(gè)數(shù)據(jù)可以訪(fǎng)問(wèn)的屬性和方法。在 TypeScript 的自我介紹中我們已經(jīng)看過(guò)幾個(gè)簡(jiǎn)單的例子,想必你也知道它實(shí)現(xiàn)這些的效果了。當(dāng)我們的項(xiàng)目較為龐大,需要由多人合作開(kāi)發(fā)時(shí),多人協(xié)作是需要溝通成本和 review 成本的。一些接口的定義,一些方法的使用,都可能因?yàn)閭€(gè)人習(xí)慣或溝通不暢導(dǎo)致邏輯實(shí)現(xiàn)的差異。而如果引入TypeScript,則會(huì)對(duì)一些實(shí)現(xiàn)進(jìn)行強(qiáng)校驗(yàn)。如果不按接口實(shí)現(xiàn),編譯就沒(méi)法通過(guò),如果對(duì)代碼質(zhì)量要求較高,可以將嚴(yán)格檢查全部打開(kāi),效果更好。
那么哪些項(xiàng)目適合用 TypeScript 開(kāi)發(fā)呢,我總結(jié)了幾類(lèi):
- 需要多人合作開(kāi)發(fā)的項(xiàng)目
- 開(kāi)源項(xiàng)目,尤其是工具函數(shù)或組件庫(kù)
- 對(duì)代碼質(zhì)量有很高要求的項(xiàng)目
來(lái)看幾個(gè)廣為人知的使用 TypeScript 開(kāi)發(fā)的經(jīng)典項(xiàng)目:
- VSCode:開(kāi)源的高質(zhì)量代碼編輯器VSCode使用TypeScript開(kāi)發(fā),所以它天生就支持 TypeScript;
- Angular & React & Vue3.0:現(xiàn)在三足鼎立的三個(gè)前端框架,Angular 和 React 已經(jīng)使用 TypeScript編寫(xiě),而在我編寫(xiě)專(zhuān)欄的同時(shí),Vue3.0 將使用 TypeScript 進(jìn)行重構(gòu),屆時(shí)三個(gè)前端框架都使用TypeScript編寫(xiě),如果使用TypeScript開(kāi)發(fā)將會(huì)得到很好的類(lèi)型支持。也可以看出,TypeScript 已經(jīng)被廣為接受。當(dāng)然了,你依然可以使用JavaScript來(lái)開(kāi)發(fā)前端項(xiàng)目,但是相信隨著 Vue3.0 發(fā)布,TypeScript將會(huì)被越來(lái)越多的開(kāi)發(fā)者所接受;
- Ant Design:使用 React 開(kāi)發(fā)項(xiàng)目的開(kāi)發(fā)者大多應(yīng)該都知道螞蟻金服開(kāi)源UI組件庫(kù)Ant Design,同樣使用TypeScript進(jìn)行編寫(xiě)。保證了代碼質(zhì)量的同時(shí),也能很好地支持開(kāi)發(fā)者使用TypeScript進(jìn)行React項(xiàng)目的開(kāi)發(fā)。如果你使用 Vue 進(jìn)行開(kāi)發(fā),Ant Design 也提供了Vue 版的組件庫(kù),風(fēng)格和功能和 React 版的保持一致,共享單元測(cè)試和設(shè)計(jì)資源,對(duì)TypeScript的支持也一樣很好。
TypeScript 在實(shí)現(xiàn)新特性的同時(shí),時(shí)刻保持對(duì)ES標(biāo)準(zhǔn)的對(duì)齊。一些ECMAScript標(biāo)準(zhǔn)沒(méi)有確定的內(nèi)容,在 TypeScript 中已經(jīng)率先支持了。所以在語(yǔ)法標(biāo)準(zhǔn)方面,可以說(shuō)TypeScript是略微領(lǐng)先的,比如類(lèi)的私有屬性和方法。ES6標(biāo)準(zhǔn)對(duì)類(lèi)的相關(guān)概念的定義中,并沒(méi)有私有屬性的概念,如果想實(shí)現(xiàn)私有屬性,需要使用一些方法hack(可以參考阮一峰的《ECMAScript 6 入門(mén)》- 私有方法和私有屬性);但是TypeScript是支持私有屬性的,可以直接使用 private 指定一個(gè)私有屬性。雖然ECMAScript新的提案提供了定義私有屬性的方式,就是使用 # 來(lái)指定一個(gè)屬性是私有的,但是到目前為止現(xiàn)在還沒(méi)有編譯器支持這種語(yǔ)法。
以上便是對(duì) TypeScript 的大致介紹,接下來(lái)我們來(lái)看下本小冊(cè)有哪些內(nèi)容。
本小冊(cè)共7大章節(jié),7個(gè)章節(jié)的內(nèi)容主要為:
- 入門(mén)準(zhǔn)備:講解學(xué)習(xí) TypeScript 和使用 TypeScript 進(jìn)行開(kāi)發(fā)的一些方法和技巧,是授你以魚(yú)之前的授你以漁,雖然后面章節(jié)會(huì)學(xué)習(xí) TypeScript 的所有語(yǔ)法,但是掌握自學(xué)TypeScript的方法技巧,可以幫助你更好更快地學(xué)習(xí) TypeScript,也方便你遇到問(wèn)題時(shí)能夠快速找到解決方案。
- 基礎(chǔ)部分:這一章都是一些較為基礎(chǔ)的知識(shí),只要你有JavaScript的基礎(chǔ)就能上手,學(xué)習(xí)起來(lái)不會(huì)有太大壓力;學(xué)習(xí)完本章后,你就可以自己使用 TypeScript 寫(xiě)一些基本的日常開(kāi)發(fā)中使用的邏輯了。
- 進(jìn)階部分:這一章你要做好心理準(zhǔn)備了。作為進(jìn)階知識(shí),不僅內(nèi)容多一些,而且有些知識(shí)較為抽象,不好理解,需要你緊跟著 Lison 多練習(xí)多思考。這一章的知識(shí)有一些在平常的業(yè)務(wù)開(kāi)發(fā)中很少用到,但是你也不可以掉以輕心,以免以后需要用到了,都不知道還有這高級(jí)內(nèi)容。
- 知識(shí)整合:這一章是對(duì)前面學(xué)習(xí)的基礎(chǔ)和進(jìn)階部分的知識(shí)的整合。學(xué)習(xí)這一章,需要前面章節(jié)的知識(shí)作為鋪點(diǎn),所以一定要把前面章節(jié)的知識(shí)掌握好哦。
- 項(xiàng)目配置及書(shū)寫(xiě)聲明文件:這一章會(huì)詳細(xì)講解項(xiàng)目的配置項(xiàng),也就是對(duì) tsconfig.json 里的配置逐條講解它的作用。之所以放到后面講,是因?yàn)槲覀兦懊鎸W(xué)習(xí)不需要用到這么多配置,但是學(xué)習(xí)所有配置,可以幫助你在開(kāi)發(fā)自己項(xiàng)目時(shí)滿(mǎn)足自己的開(kāi)發(fā)需求。書(shū)寫(xiě)聲明文件需要用到前面的語(yǔ)法知識(shí),學(xué)會(huì)書(shū)寫(xiě)聲明文件,我們就可以在使用了一些冷門(mén)的沒(méi)有聲明文件的JS庫(kù)時(shí),自行為它們書(shū)寫(xiě)聲明文件,以便我們開(kāi)發(fā)使用。
- 項(xiàng)目實(shí)戰(zhàn):這一章是實(shí)戰(zhàn)部分,通過(guò)使用 TypeScript+Vue 開(kāi)發(fā)一個(gè)簡(jiǎn)單后臺(tái)。我會(huì)帶著你從零創(chuàng)建一個(gè)項(xiàng)目,并實(shí)現(xiàn)目錄中列出的功能,幫助你將學(xué)到的知識(shí)在實(shí)際開(kāi)發(fā)中進(jìn)行運(yùn)用。即是對(duì)前面知識(shí)的復(fù)習(xí),也是對(duì)理論知識(shí)到實(shí)踐的轉(zhuǎn)化,做完這個(gè)項(xiàng)目,相信你會(huì)對(duì)TypeScript項(xiàng)目開(kāi)發(fā)有一個(gè)新的認(rèn)識(shí),再去獨(dú)立開(kāi)發(fā)項(xiàng)目,會(huì)輕松很多。
- 寫(xiě)在最后:這一章是一個(gè)總結(jié)。相信學(xué)到這一章的時(shí)候,你已經(jīng)對(duì) TypeScript 有了整體認(rèn)知了。我將會(huì)在本章分享一些我的開(kāi)發(fā)經(jīng)驗(yàn),幫助你在項(xiàng)目開(kāi)發(fā)中少走彎路。
好了,在聽(tīng)完 TypeScript 的自我介紹和發(fā)展趨勢(shì)的了解之后,讓我們一起愉快地進(jìn)入TypeScript 的學(xué)習(xí)中去吧。


