--- # typescript 筆記 ## 前言 - 一個基於 JavaScript 的超集合(SuperSet) - 提供型別系統(Type System),能夠在開發時期宣告型別 - 支援 ECMAScript,可將 TS 檔編譯成 JS 檔給瀏覽器解讀 ## 型別系統 Type System 由於javescript是弱型別語言,typescript的出現就是要解決這個問題 typescript就是javascript的延伸其支援ECMAScript規範所以可以支援js代碼 **舉例typescript與javascript差異 :** 原生javascript : ![](https://i.imgur.com/RhMczog.png) typescript : ![](https://i.imgur.com/TRbOPU4.png) 以上的範例可以看出typescript是如何註記型別,typescript的原始型別有以下幾種 : ### Boolean 使用 boolean 定義布林值型別 : ``` typescript= let isToggle:boolean = false ``` 注意:使用建構函式 Boolean 建立的物件不是布林值: ``` typescript= let isToggle:boolean = new Boolean(1) ``` 直接呼叫Boolean返回的是一個boolean型別 : ``` typescript= let isToggle:boolean = new Boolean(1) ``` 在typescipt中,boolean是基本型別,而Boolean是建構函式 ### String 使用 String 定義字串型別 : ``` typescript= let myName:string = "Danny" ``` typescript 支援樣本字串: ``` typescript= let age:number = 10 let myName:string = 'Danny' let sentense = `Hellow my Name is ${myName} my age is ${age}` ``` 使用樣本字串創建type: ``` typescript= type Direction = 'row'|'column' type Position = 'center'|'right'|'left' type PositionVarants = `${Position} - ${Position}` ``` 型別推論結果是 : ![](https://i.imgur.com/mbZrPP2.png) 註 : typescript會透過樣本字串結合新型別 ### Number 使用 Number 定義字串型別 : ``` typescript= let decLiteral: number = 6; let notANumber: number = NaN; let infinityNumber: number = Infinity; ``` ### 空值 在typescrupt可以透過void,表示沒有返回任何值的函式: ``` typescript= function sayHellow():void{ console.log('Hellow world') } ``` ### Null 和 Undefined 使用 **null** 和 **undefined** 來定義這兩個原始資料型別: ``` typescript= let u: undefined = undefined; let n: null = null; ``` undefined 和 null 是所有型別的子型別。也就是說 undefined 型別的變數,可以賦值給 number 型別的變數: ``` typescript= let num:number = undefined ``` ### 陣列 使用 []定義原始型別集合: ``` typescript= let animals:string[]=['lion','pig'] let peopleNo:number[]=[10,5] ``` ### 任意值 賦予變數任何型別: ``` typescript= let addressNO:any=281 ``` ### 列舉型別 enum 以下為例 : ``` typescript= enum Color {Red,Green,Blue}//output : 0,1,2 let c:Color =Color.Green //1 ``` 編譯結果: ``` typescript = var Color; (function (Color) { Color[Color["Red"] = 0] = "Red"; Color[Color["Green"] = 1] = "Green"; Color[Color["Blue"] = 2] = "Blue"; })(Color || (Color = {})); ``` 可以看到enum的概念是一個object,值=鍵,鍵=值 ## 型別推論(Type Inference) >TypeScript會依據型別規則推導出一個資料型別 以下方程式碼為例: ```typescript= let myLuckyNumber = 12 ``` 等同於上方: ```typescript= let myLuckyNumber:number = 12 ``` 如經過TS型別推論後的變數,再指定其他值會報錯: ```typescript= let myLuckyNumber:number = 12 myLuckyNumber = '7' // index.ts(2,1): error TS2322: Type 'string' is not assignable to type 'number'. ``` ### e.g.自動註記 ![](https://i.imgur.com/0H4fk4B.png) ``` message變數就被推論為string ``` ## 型別斷言 Type Assertion > 當最後需要改變變數型別時,為了避免出現警告錯誤,這個機制就是『型別斷言』 型別斷言有兩種寫法 - 第一種 :`<型別值>` ``` typescript= let code: any = 'Hello'; let helloCode = <string> code; ``` - 第二種 :`值as型別` ``` typescript= let code: any = 'Hello'; let helloCode =code as string; ``` ## Utility Types ### Required<Type> 簡單舉個Utility Types例子 : ```typescript= interface Props { a?: number; b?: string; } const obj2:Required<Props>={ a:5 } //obj2會報錯因為b已經不是可選項的屬性 ``` Required<Type>是typescript原生的type可以讓型別中的可選項變成reuired [更多範例 ...](https://www.typescriptlang.org/docs/handbook/utility-types.html) ## interface vs type ## 相同點 ### type ```typescript= type User={ name:string age:number } let user:User={ name:'Danny', age:20 } ``` 以上我們定義一個型別User他有name、age兩個,透過user指定User型別告訴蓋變數有name、age以及其對應的型別 ### interface ```typescript= interface User={ name:string age:number } let user:User={ name:'Danny', age:20 } ``` 註 :與type寫法類似但對typescript來說是不同的解釋,type是個型別用引而interface是產生一個新型別,interface算是一個介面的延伸如class一樣介面可以extend屬性但type不能,如以下例子 : ## 不同點 ### overwrite ```typescript= interface info { personName:string } interface info { addressNo:number } ``` 介面info可以透過複寫的方式延伸型別 ### extend ```typescript= interface Mailable { send(email: string): boolean queue(email: string): boolean } interface FutureMailable extends Mailable { later(email: string, after: number): boolean } ``` 註 :以上的FutureMailable就是一個繼承的概念,FutureMailable擁有Mailable的屬性同時增加later函式的方法 ### 一個class可以繼承多個屬性 ```typescript= interface Mailable { send(email: string): boolean queue(email: string): boolean } interface FutureMailable { later(email: string, after: number): boolean } class Mail implements FutureMailable,Mailable { later(email: string, after: number): boolean { console.log(`Send email to ${email} in ${after} ms.`); return true; } send(email: string): boolean { console.log(`Sent email to ${email} after ${after} ms. `); return true; } queue(email: string): boolean { console.log(`Queue an email to ${email}.`); return true; } } ``` 以上敘FutureMailable為例,在class中使用interface去繼承型別使用的關鍵字是implements,如需使用多個介面只要在後面新增就好。 ## Mixins <T>為typescript optional type的方法,只需要再函數括號前新增就好 ```typescript= function base<T>() { class Base { static prop: T; } return Base; } function derivedg<T>(){ class Derived extends base<T>() { static anotherProps:T } return Derived } class Spec extends derivedg<string>(){} Spec.anotherProps//string Spec.prop//string ``` 上述是一個class的mixins設定,derived函數是繼承Base函數的方法,class Spec可以繼承derived回敷函數的調用結果讓Spec繼承class Base、Derived,也因為optional type的關係Spec.anotherProps的型別結果是String ## typescript 編譯設定 全局安裝typescript ``` npm install typescript -g ``` mac 安裝全域套件記得加sudo ``` sudo npm install typescript -g ``` 初始化ts專案 ``` tsc --init ``` 專案中會跑出tsconfig.json這支檔案 ![](https://i.imgur.com/saMVbvf.png) 註 :tsconfig.json為ts編譯的設定檔案 例如outDir就是要檔案編譯後要放的資料夾 ![](https://i.imgur.com/fuUTqlg.png) typescript很貼心在tsconfig.json中每一個option都有解釋說明用法非常直觀。 ### 小結 儘管javascript自由度很高,但在型別使用上卻有缺陷,時常搞不清楚api呼叫後的結果是什麼,typescript的出現就是要補足這個問題,typescript的主要概念有兩個,其一Type Inference,自動推倒變數結果防止變數型別錯亂,其二就是Type Assertion,當一個變數可能會有多個以上的型別時,就可以夠過斷言決定變數想要的結果為何,也算是typescript提供的自由度。12