[TOC] #### 1. TypeScript 是什么 ? --- **編程語(yǔ)言的類(lèi)型: 靜態(tài)類(lèi)型語(yǔ)言、動(dòng)態(tài)類(lèi)型語(yǔ)言** 靜態(tài)類(lèi)型語(yǔ)言的數(shù)據(jù)類(lèi)型是在編譯期間檢查的。也就是說(shuō),在編寫(xiě)程序時(shí)就要聲明變量的數(shù)據(jù)類(lèi)型。如: Java 動(dòng)態(tài)類(lèi)型語(yǔ)言是指在運(yùn)行期間才去做數(shù)據(jù)類(lèi)型檢查的語(yǔ)言。也就是說(shuō),永遠(yuǎn)不用給變量指定數(shù)據(jù)類(lèi)型。如: Python、PHP **TypeScript 究竟是什么 ?** typescript 官網(wǎng): [https://typescriptlang.org](https://typescriptlang.org) TypeScript 是 Type 和 JavaScript 的結(jié)合,TypeScript 就是將不看重類(lèi)型的動(dòng)態(tài)語(yǔ)言 JavaScript,變成關(guān)注類(lèi)型的靜態(tài)語(yǔ)言 #### 2. 為什么要學(xué)習(xí) TypeScript ? --- **程序更容易理解** ts 可以約定函數(shù)或方法輸入輸出的參數(shù)類(lèi)型,外部條件等 **效率更高** 在不同的代碼塊和定義中進(jìn)行跳轉(zhuǎn)、代碼補(bǔ)全、接口提示 **更少的錯(cuò)誤** 編譯期間能夠發(fā)現(xiàn)大部分錯(cuò)誤,杜絕一些比較常見(jiàn)的錯(cuò)誤 #### 3. 安裝 TypeScript --- 全局安裝 typescript ```bash npm install -g typescript ``` 查看版本 ```bash tsc -V ``` 創(chuàng)建 helloworld.ts ```javascript const hello = (name: string) => { } ``` 編譯 ```bash tsc helloworld.ts ``` 補(bǔ)充: 命令行運(yùn)行 ts 文件需要安裝 ts-node 包 ```sh npm install -g ts-node ``` 然后就可以使用 ts-node 命令運(yùn)行 ts 文件了 ```sh ts-node helloworld.ts ``` #### 4. 原始數(shù)據(jù)類(lèi)型和 any 類(lèi)型 --- 最新的 ESMAScript 標(biāo)準(zhǔn)定義了八種數(shù)據(jù)類(lèi)型 七種原始數(shù)據(jù)類(lèi)型: number、string、boolean、undefined、null、BigInt、Symbol。另外一種是 Object 注意: undefined、null 是所有類(lèi)型的子類(lèi)型,所以下面寫(xiě)法是正確的 ```javascript let age: number = undefined ``` 頂級(jí)類(lèi)型: any,可以接收所有數(shù)據(jù)類(lèi)型的數(shù)據(jù) ```javascript let all: any = null; all = true; all = 123456; all = 'liang'; ``` #### 5. 數(shù)組和元組(tuple) --- 聲明一個(gè) number 類(lèi)型的數(shù)組,數(shù)組元素必須為 number 類(lèi)型 ```javascript let numArr: number[] = [1, 2, 3] ``` 元組: 給數(shù)組元素分別指定數(shù)據(jù)類(lèi)型 ```javascript // 定義元組時(shí),數(shù)組元素個(gè)數(shù)不能超過(guò)聲明的類(lèi)型個(gè)數(shù) let user: [string, number] = ['liang', 23] // 但可以追加數(shù)組元素,追加的數(shù)據(jù)類(lèi)型必須在聲明的類(lèi)型中,也就是 string, number user.push(10) ``` #### 6. Interface 接口 --- Interface 不是 JavaScript 中的概念,而是 ts 作類(lèi)型檢查用的,所以 ts 在編譯后,Interface 是不會(huì)被轉(zhuǎn)譯過(guò)去的 interface 描述對(duì)象類(lèi)型 ```javascript // 定義接口 interface Person { // 只讀屬性 readonly id: number, // 必須屬性 name: string, // 可選屬性 age?: number, } // 變量使用接口 let user: Person = { id: 1, name: "liang", // age: 23, // 可選屬性,定義不定義都可以 // like: "code", // 對(duì)象文字可以只指定已知屬性,但 “like”不在接口“Person”中 } // user.id = 2 // 報(bào)錯(cuò): 因?yàn)?id 是只讀屬性, 無(wú)法修改 ``` #### 7. 函數(shù)中聲明數(shù)據(jù)類(lèi)型 --- 普通的聲明函數(shù),函數(shù)的結(jié)果返回 number 類(lèi)型 ```javascript /** * 可選參數(shù)z: 省略時(shí)為 undefined */ function add(x: number, y: number, z?: number): number { if (typeof z === 'number') { return x + y + z } else { return x + y } } ``` 函數(shù)表達(dá)式聲明的函數(shù)返回的是一個(gè)函數(shù)類(lèi)型 ![](https://img.itqaq.com/art/content/330a4854424aee2bbd1cf3733a3d8257.png) ```javascript const add = (x: number, y: number, z?: number): number => { if (typeof z === 'number') { return x + y + z } else { return x + y } } // 在 ts 中 : 后面都是在聲明類(lèi)型,和實(shí)際代碼邏輯無(wú)關(guān) let abc: (x: number, y: number, z?: number) => number = add // interface 描述函數(shù)類(lèi)型 interface ISum { (x: number, y: number, z?: number): number } let def: ISum = add ``` #### 8. 類(lèi)型推論 (type inference) --- 官方文檔: [https://www.typescriptlang.org/docs/handbook/type-inference.html](https://www.typescriptlang.org/docs/handbook/type-inference.html) 當(dāng)我們把數(shù)據(jù)賦給變量時(shí),沒(méi)有指定數(shù)據(jù)類(lèi)型,ts 會(huì)自動(dòng)推測(cè)出一個(gè)類(lèi)型,如下圖: ![](https://img.itqaq.com/art/content/a6cd4cf6961def297e16174e37443641.png) 因?yàn)?ts 已經(jīng)將變量 x 的類(lèi)型推斷為 number,那么當(dāng)我們給變量 x 賦值一個(gè) string 類(lèi)型的數(shù)據(jù)則會(huì)提示錯(cuò)誤 ![](https://img.itqaq.com/art/content/c47d202809f4e96be7e204b1dc2bc947.png) #### 9. 聯(lián)合類(lèi)型 --- ```javascript // 聯(lián)合類(lèi)型 union types let numOrString: number | string numOrString.toString() // toString() 是 number|string 的共有方法 // numOrString.length // 報(bào)錯(cuò): length 不是共有屬性, string 有,但 number 沒(méi)有 ``` #### 10. 泛型 Generics --- 基礎(chǔ)使用 ```javascript function echo<T>(arg: T): T { return arg } const str: string = 'liang' const num: number = 123456 console.log(str, num); ``` 交換數(shù)組中兩個(gè)元素的位置 ```javascript function swap<T, U>(tuple: [T, U]): [U, T] { return [tuple[1], tuple[0]] } const res1 = swap(['123', 456]) console.log(res1); ``` 約束泛型 ```javascript interface ILength { length: number } // 約束泛型 function echoWithArr<T extends ILength>(args: T): T { console.log(args.length); return args } echoWithArr('12345') echoWithArr(['1', 2]) echoWithArr({width: 10, length: 30}) ``` #### 11. 類(lèi)型別名 ---- 類(lèi)型別名的作用: 復(fù)雜的類(lèi)型名簡(jiǎn)單化 ```javascript // 普通方式 let sum: (x: number, y: number) => number const result1 = sum(1, 2) // 類(lèi)型別名 // 語(yǔ)法格式: type 別名 = 全名 type PulsType = (x: number, y: number) => number let sum2: PulsType const result2 = sum2(1, 2) // 聯(lián)合類(lèi)型的別名 type strOrNum = string | number let data3: strOrNum data3 = 23 data3 = 'liang' // data3 = true // 報(bào)錯(cuò) ``` #### 12. 字面量 ---- ```javascript const str: 'name' = 'name' // const str: 'name' = 'name2' // 報(bào)錯(cuò) const number: 1 = 1 type Directions = 'Up' | 'Down' | 'Left' | 'Right' let toWhere: Directions = 'Left' ``` #### 13. 交叉類(lèi)型 ```javascript interface IName { name: string } type IPerson = IName & {age: number} let person: IPerson = {name: 'liang', age: 23} ```