摘要:為了由簡入繁,不妨將這些類型劃分為基本類型復(fù)合類型。以下將漸進(jìn)式的對(duì)的這些類型進(jìn)行了解。實(shí)際上,有一種屬性描述對(duì)象,是通過獲取的。但無論如何,類型檢查是可以排除大部分錯(cuò)誤的。在函數(shù)的類型聲明中,繼續(xù)來鞏固這條規(guī)則的寫法。
幾個(gè)月前把 ES6 的特性都過了一遍,收獲頗豐。現(xiàn)在繼續(xù)來看看 TypesScript(下文簡稱為 “TS”)。限于經(jīng)驗(yàn),本文一些總結(jié)如有不當(dāng),歡迎指正。
概述官網(wǎng)有這樣一段描述:
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
說的是 TS 是 JS 的超集,并且可以編譯成普通的 JS。
其中, 超集 的定義是:
如果一個(gè)集合 S2 中的每一個(gè)元素都在集合 S1 中,且集合 S1 中可能包含 S2 中沒有的元素,則集合 S1 就是 S2 的一個(gè)超集,反過來,S2 是 S1 的子集。
而實(shí)際上,“超出” 的部分主要就是 “類型系統(tǒng)”。因此可以這樣歸納:
TS ≈ ES6 + 類型系統(tǒng)
ES6 是 ES5 轉(zhuǎn)向主流語規(guī)格的一個(gè)重要升級(jí),順著這個(gè)角度看,TS 讓這門語言披上一層類型的外衣,直接演變成一種強(qiáng)類型的語言;從相反角度看,TS 將編程語言們一些主流的特性引入到了 JS 的世界。
平穩(wěn)過渡TypeScript 設(shè)計(jì)巧妙,兼具微軟工業(yè)化的水準(zhǔn)。首先,它僅靠一行命令,就融入到了廣大前端人的世界:
npm install -g typescript
然后由你隨便挑一個(gè)曾編寫的 .js 腳本文件(不妨叫做hello.js),不用對(duì)內(nèi)容做任何修改,直接將文件后綴改成 .ts。這樣,你就已經(jīng)完成了一份 TypeScript 腳本的編寫!
然后編譯它:
tsc hello.ts
OK,你已經(jīng)平滑過渡到了 TS 的世界。就是這么簡單!
當(dāng)然這只是“一小步”,似乎后邊還有無數(shù)的坑要填。不用擔(dān)心,TS 已經(jīng)填平了大部分的坑!
比如,時(shí)下最流行的 gulp,webpake 工具,只需做一些簡單的配置,就能接引入TypeScript 進(jìn)行編譯;同時(shí)為了能與 React 完美融合,TS 引入了與 JSX 類似的 TSX 語法。當(dāng)然,TS 在 Angular、Vue.js 以及 Node.js 中也是暢通的......
坑都填平了,大家過渡起來自然順心順手。
基本類型與 ES6 一脈相承的,同時(shí)也接軌大部分強(qiáng)類型語言,TS 的類型大概有這些:
1),Number、Boolean、String、Null 、undefined、Symbol
2), Array、Function、Object
3),Tuple、enum、Void、 Never、Any
TS 作為 JS 的一個(gè)超集,在 JS 的基礎(chǔ)上擴(kuò)展了一些非常有用的類型。第 3)中的類型就是從一些強(qiáng)類型語言引入的類型。
為了由簡入繁,不妨將這些類型劃分為:基本類型、復(fù)合類型。復(fù)合類型 一般由 基本類型 構(gòu)成。以下將漸進(jìn)式的對(duì) TS 的這些類型進(jìn)行了解。
如何做類型聲明?強(qiáng)類型語言都有一套類型聲明的語法規(guī)則,TS 也不例外。TS 采用類型注釋的寫法,像這樣將一個(gè)帶冒號(hào)的注釋,置于聲明變量名之后,就構(gòu)成了 TS 類型聲明的語法。
let str : string = "hello typescript";
JAVA 的寫法是相反的,但無實(shí)質(zhì)差別:
String str = "hello java";
這樣的注釋如同一種補(bǔ)充說明,后文將簡稱它為 “冒號(hào)注釋”,熟悉書寫規(guī)則,有利于快速進(jìn)入到 TS 的代碼世界。
實(shí)際上,ES6 有一種屬性描述對(duì)象,是通過Object.getOwnPropertyDescriptor(obj, key) 獲取的。
let obj = { set name(val) {} } Object.getOwnPropertyDescriptor(obj, "name"); // { // configurable: true // enumerable: true // get: undefined // set: ? a(val) // }
如果將 setter 類型的 name 方法適當(dāng)改寫,我們甚至可以實(shí)現(xiàn) obj.name 賦值的類型檢查功能,也非常有意思。
同樣的,冒號(hào)注釋 : string 也可以理解為對(duì)一個(gè) str 變量的描述。憑借這個(gè)注釋的描述,TS 的類型編譯器就能進(jìn)行類型檢查了。
建立了類型的認(rèn)知后,繼續(xù)跑馬圈地,鞏固認(rèn)知。其中,Function、 Never、Any 規(guī)則稍顯復(fù)雜,但也沒有什么特別的,留后細(xì)說。
簡單的基本類型// boolean 類型 let isBool: boolean = 1 < 5; // string 類型 let str: string = "hello world"; // number 類型 let num: number = 123; // void 類型 let unusable: void = undefined; // undefined 類型 let u: undefined = undefined; // null 類型 let n: null = null; //Symbol 類型 // 類型 symbol 小寫也能編譯通過 let sym: Symbol = Symbol("hello");簡單的復(fù)合類型。
// object 類型 let obj : object = {}; let arrObj : object = []; let funcObj : object = () => {}; // array 類型 let arrNum : number[] = [1, 2, 3] let arrStr : string[] = ["a", "b", "c"] let arrObj : object[] = [{}]; // 元組 類型 let tup : [number, string] = [1, "hello"]; // 枚舉類型 enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
可謂一覽無余,類型的語法就是冒號(hào)注釋,僅憑這一條,60~70% 的情況你都無需擔(dān)心自己的類型書寫有誤。
一個(gè)靈活的子類型但 JS 的動(dòng)態(tài)類型太靈活了,null 和 undefined 的相似性, Array、Function 和 Object的糾纏不清的關(guān)系,僅憑一招恐怕還很難駕馭的住 JS 的 “多動(dòng)癥” 般的類型。比如:
// boolean 類型接收這樣的賦值 let isBool_n: boolean = null; let isBool_u: boolean = undefined; // void 類型接收這樣的賦值 let unusable: void = undefined; unusable = null; // Symbol 類型接收這樣的賦值 let sym: Symbol = Symbol("hello"); sym = null; sym = undefined; // object 類型接收這樣的賦值 let obj : object = {}; obj = null; obj = undefined;
它們都能編譯通過。但是 null 不屬于 boolean 類型,undefined也并不屬于object 類型,為什么能通過類型檢查?
事實(shí)上,undefined 和 null 是所有類型的子類型。也就是說,它們倆可以作為值賦給任何類型的變量。甚至,它們倆可以互相賦值給對(duì)方。
// undefined 類型 let u: undefined = null; // null 類型 let n: null = undefined;
有了這一條規(guī)則,就能解釋一些 “復(fù)合類型” 中遇到的問題:
let arrNum: number[] = []; let arrStr: string[] = []; // undefined 也屬于 number 類型 let arrNum: number[] = [undefined]; // undefined 也屬于 object 類型 let obj : object = undefined;
有了這條規(guī)則,我們可以大膽的寫 TS 的類型聲明了。
但太過放開的規(guī)則——本文姑且稱之為 “混雜模式”,又似乎一下子讓 TS 退回到了 JS 的動(dòng)態(tài)類型的原始狀態(tài)了,讓習(xí)慣了強(qiáng)類型的同學(xué)容易懵掉,也讓從 JS 轉(zhuǎn) TS 的同學(xué)體會(huì)不到強(qiáng)類型的好處。
畫條界限好在,TS 設(shè)計(jì)了一套巧妙的類型系統(tǒng),猶如給 JS 披上 了一層強(qiáng)大的盔甲。
TS 在 “混雜模式” 下,可能存在這樣的風(fēng)險(xiǎn),就是:編譯正確,運(yùn)行出錯(cuò)。比如:
// 無意獲得一個(gè) undefined 作為初始值 let init_name = undefined; let nameList: string[] = [init_name]; console.log(nameList[0].split("_")); // 運(yùn)行報(bào)錯(cuò)
在非 “嚴(yán)格模式” 下,上述 TS 代碼編譯無誤,但是真正拿到頁面去運(yùn)行編譯結(jié)果時(shí),出現(xiàn)錯(cuò)誤。
那怎么辦呢?要相信 TS 強(qiáng)大的類型系統(tǒng),只需一項(xiàng)配置,就能將編譯切換成 “嚴(yán)格模式”:
// 在配置文件 tsconfig.json 中增加一項(xiàng) "compilerOptions": { // ... "strictNullChecks": true },
再次執(zhí)行編譯,就會(huì)出現(xiàn)錯(cuò)誤提示信息:
error TS2322: Type "undefined[]" is not assignable to type "string[]".
TypeScript 官方教程鼓勵(lì)盡可能地使用 --strictNullChecks,因此這里也強(qiáng)烈建議配置該屬性再進(jìn)行編譯,這樣能很好的發(fā)揮 TS 類型檢查的作用。
網(wǎng)開一面和漏網(wǎng)之魚TS 編譯通過指的是類型檢查符合類型系統(tǒng)的規(guī)則,運(yùn)行 OK 則是編譯后的 JS 本身執(zhí)行無誤。編譯通過,不等于運(yùn)行OK,即使在 “嚴(yán)格模式” 下也是這樣的,所以千萬別以為編譯通過了就完事了。
以 Any 類型為例,在 --strictNullChecks 模式下:
// TS 代碼 let anyThing: any = "hello"; console.log(anyThing.myName); // 編譯后的 ES6 let anyThing = "hello"; console.log(anyThing.setName("world"));
很顯然,編譯后的 anyThing.setName("world") 會(huì)運(yùn)行報(bào)錯(cuò)。
當(dāng)然, Any 類型略有點(diǎn)特殊,因?yàn)樗梢援?dāng)做是 TS 平滑退化到 JS 的一個(gè)類型,官網(wǎng)教程也有這樣解說:
在對(duì)現(xiàn)有代碼進(jìn)行改寫的時(shí)候,any類型是十分有用的,它允許你在編譯時(shí)可選擇地包含或移除類型檢查。
那問題又回來了,是否除了 Any 類型,其他編譯OK,代碼就運(yùn)行無錯(cuò)呢?鑒于筆者正在入門,經(jīng)驗(yàn)有限,不敢給這個(gè)結(jié)論。但無論如何,類型檢查是可以排除大部分錯(cuò)誤的。
最后,編譯的時(shí)候,盡量選擇編譯成 ES6 (前提是項(xiàng)目是用 ES6 寫的)。配置是:
"compilerOptions": { "target": "es6" // "es5" }只有一條規(guī)則
TS “冒號(hào)注釋” ——就這一條規(guī)則,貫穿始終。在函數(shù)的類型聲明中,繼續(xù)來鞏固這條規(guī)則的寫法。
類型聲明只對(duì)變量負(fù)責(zé),對(duì)于函數(shù),需考察輸入——函數(shù)參數(shù)(也是變量)、輸出——函數(shù)返回值兩個(gè)要素。
因?yàn)楹瘮?shù)的特殊結(jié)構(gòu),所有 “冒號(hào)注釋” 規(guī)則的寫法要特別了解下:
// 聲明函數(shù) function add(x: number, y: number): number { return x + y; } // 函數(shù)直接量 let myAdd = function(x: number, y: number): number { return x + y; };
可以看到,參數(shù)的 “冒號(hào)注釋” 和一般變量沒有任何差別。倒是函數(shù)輸出類型注釋有點(diǎn)特別——試想,: number 緊隨函數(shù)名之后或者 function 關(guān)鍵字之后,是不是容易被誤解為函數(shù)名的一部分?是不是對(duì)編譯引擎不太友好?從這個(gè)角度看,注釋置于) 之后最為合理。
對(duì)了,一個(gè)疑問一直從頭保留到現(xiàn)在:要是一個(gè)變量是 function 類型,那類型注釋怎么寫,又不能拿 function 關(guān)鍵字去做類型注釋?
let myAdd: (x: number, y: number) => number = function(x: number, y: number): number { return x + y; };
其中等號(hào)前邊的 : (x: number, y: number) => number 就代表了函數(shù)類型。它仍然在結(jié)構(gòu)上符合 “冒號(hào)注釋” 的規(guī)則,只不過冒號(hào)后邊是一串表達(dá)式。這樣的結(jié)構(gòu)有點(diǎn)像 Python 中的推導(dǎo)式的概念。
好了,補(bǔ)上這一塊重要的缺漏,本文就完成了所有基本類型的類型聲明的解釋。憑借一條規(guī)則,希望在 TS 學(xué)習(xí)上暢通無阻的敲代碼~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89542.html
摘要:靜態(tài)屬性靜態(tài)方法目前支持靜態(tài)方法表示,類屬性及靜態(tài)屬性目前作為提案還未正式成為標(biāo)準(zhǔn)。在中,抽象類不能用來實(shí)例化對(duì)象,主要做為其它派生類的基類使用。不同于接口,抽象類可以包含成員的實(shí)現(xiàn)細(xì)節(jié)。中也是這樣規(guī)定的抽象類不允許直接被實(shí)例化。 嘗試重寫 在此之前,通過《JavaScript => TypeScript 入門》已經(jīng)掌握了類型聲明的寫法。原以為憑著那一條無往不利的規(guī)則,就可以開開心心的...
摘要:前言這個(gè)輪子已經(jīng)有很多人造過了,為了不重復(fù)造輪子,我將本項(xiàng)目以三階段實(shí)現(xiàn)大家可以在中的查看純前端后端前端后端前端希望能給大家一個(gè)漸進(jìn)學(xué)習(xí)的經(jīng)驗(yàn)。 前言 Vue+Socket.io這個(gè)輪子已經(jīng)有很多人造過了,為了不重復(fù)造輪子,我將本項(xiàng)目以三階段實(shí)現(xiàn)(大家可以在github中的Releases查看): 純前端(Vuex) 后端+前端(JavaScript) 后端+前端(TypeScrip...
先為大家介紹在vue項(xiàng)目中 jsconfig.json 官方說明:當(dāng)您在工作空間中有一個(gè)定義項(xiàng)目上下文的jsconfig.json文件時(shí),JavaScript體驗(yàn)會(huì)得到改進(jìn)?! 「攀觥 ∧夸浿写嬖趖sconfig.json文件表明該目錄是 TypeScript 項(xiàng)目的根目錄。該tsconfig.json文件指定編譯項(xiàng)目所需的根文件和編譯器選項(xiàng)?! avaScript 項(xiàng)目可以使用jscon...
摘要:眾所周知,是弱類型的語言。因此在一些不注意的地方容易犯錯(cuò)誤。通過得到這兩個(gè)值,是字符串類型的數(shù)字,很顯然返回之前已經(jīng)了。反思雖然寫的是弱類型的,但是在有明確類型的情況下,最好還是轉(zhuǎn)換成對(duì)應(yīng)的類型進(jìn)行比較。 眾所周知,js是弱類型的語言。因此在一些不注意的地方容易犯錯(cuò)誤。在此記錄一下前幾天寫代碼的時(shí)候,判斷兩個(gè)值相比較的結(jié)果來進(jìn)行下一步的操作。通過ajax得到這兩個(gè)值,是字符串類型的數(shù)字...
摘要:入門,第一個(gè)這是一門很新的語言,年前后正式公布,算起來是比較年輕的編程語言了,更重要的是它是面向程序員的函數(shù)式編程語言,它的代碼運(yùn)行在之上。它通過編輯類工具,帶來了先進(jìn)的編輯體驗(yàn),增強(qiáng)了語言服務(wù)。 showImg(https://segmentfault.com/img/bV1xdq?w=900&h=385); 新的一年不知不覺已經(jīng)到來了,總結(jié)過去的 2017,相信小伙們一定有很多收獲...
閱讀 1371·2021-09-10 10:51
閱讀 2835·2019-08-30 15:54
閱讀 3377·2019-08-29 17:11
閱讀 936·2019-08-29 16:44
閱讀 1399·2019-08-29 13:47
閱讀 1095·2019-08-29 13:47
閱讀 1495·2019-08-29 12:23
閱讀 1052·2019-08-28 18:18