因為工作需求,有需多缺乏的技能需要補齊,TypeScript 就是其中一項。 上班看不懂的時候邊查詢,空閒時間再來上課不足不懂的知識點,但還是得透過文章的整理來好好消化一下! 既然要開始介紹 TypeScript 就先來說說使用它的原因吧。
為什麼使用 TypeScript
使程式碼更容易理解 (如函式需傳入的參數可以明確設定型別)
減少程式碼撰寫的錯誤
可以完全兼容JavaScript,此外能與 ES6 完美結合,並提供更多支援寫法。
安裝介紹
就是直接到官方網站查看,依需求安裝
npm install -g typescript
型別介紹 從 JavaScript 型別分類開始
字串 string
和ES6一樣,可以使用[字串樣板 Template Literals]1 2 3 let firstName :string = 'NaNa' let message : string = `Hello,${firstName} `
布林值 boolean
布林值是最基礎的資料型別,在 TypeScript 中,使用 boolean 定義布林值型別:
1 let isDonw :boolean = false
注意:使用建構函式 Boolean 建立的物件不是布林值:
事實上 new Boolean() 返回的是一個 Boolean 物件1 2 3 4 let createdByNewBoolean : boolean = new Boolean (1 );
1 在 TypeScript 中,boolean 是 JavaScript 中的基本型別,而 Boolean 是 JavaScript 中的建構函式。
數值 number 1 2 3 let age :number = 10 let notANumber : number = NaN ;let infinityNumber : number = Infinity ;
Null 和 Undefined
與 void 的區別是,undefined 和 null 是所有型別的子型別
unfefined 可以賦值給number類型的變數
陣列被赋值為 undefined 或 null 不会报错
let num:number = undefined
1 2 3 4 5 6 let u : undefined = undefined ;let n : null = null ;let u : undefined ;let num : number = u;
void
通常用在當函式沒有回傳值時。
而 void 型別的變數不能賦值給 number 型別的變數:1 2 3 4 let u : void ;let num : number = u;
any
在任意值上任何属性都是允許的
當有明確型別時,應避免使用 any
因為 any 可以任意調用方法和屬性,很有可能出現錯誤(就喪失類型檢查的意義) 如果是 any 型別,則允許被賦值為任意型別
1 2 let myFavoriteNumber : any = 'seven' ;myFavoriteNumber = 7 ;
未宣告型別的變數 變數如果在宣告的時候,未指定其型別,那麼它會被識別為任意值型別:
1 2 3 4 5 let something;something = 'seven' ; something = 7 ; something.setName ('Tom' );
陣列 Array 與 元組 Tuple 陣列
在想宣告的型別後面加上[],宣告為某個型別的Array1 let idList :number [] = [1 ,2 ,3 ]
使用陣列泛型,Array <元素型別>1 let list :Array <number > = [1 ,2 ,3 ]
注意,當已經宣告這是個數字陣列
要 push 字串進去,會出現錯誤1 2 let list :Array <number > = [1 ,2 ,3 ]list.push ("4" )
元組 Tuple
剛剛的陣列將同一類型的數據放在一起,但是,想加入不同型別的數據怎麼辦?
表示方式與陣列相似,將型別寫在[]
有固定長度和元素型別的陣列1 2 3 4 let user : [string , number ] = ['viking' , 20 ]user = ['molly' , 20 , true ]
元組
物件的型別——介面 (Interface)
Interface 可以用來定義物件,還有由物件所延伸的型別(例如,陣列、函式)
age?: number;
在該屬性後面加上 ?
表示為可選屬性 ,也就是在宣告新的物件時,可以彈性加入或不加入age (也不會報錯)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 interface Person { name : string ; age : number ; } let NaNa : Person ={ name : 'NaNa' , age : 20 } interface Person { name : string ; age?: number ; } let NaNa : Person = { name : 'NaNa' }
唯讀屬性
readonly 是用在屬性上面
希望物件中的一些欄位只能在建立的時候被賦值,那麼可以用 readonly 定義唯讀屬性
1 2 3 4 5 6 7 8 9 10 11 12 13 interface Person { readonly id : number ; name : string ; age?: number ; } let Vic : Person ={ id :1 , name : 'Vic' , age : 20 } Vic .id = 9527
函式型別
函式可以作為參數、可以存入陣列,可以被另外一個函式返回、可以被賦值另外一個變數
函式是由兩部分構成,一個是輸入(通過不同參數來實現),二為輸出(就是函數的返回結果)例子一
設定參數型別、返回的型別
若參數設定了 x、y兩個,也就只能放入兩個1 2 3 4 function add (x: number , y: number ): number { return x + y }
例子二
1 2 3 4 5 6 7 8 function add (x: number , y: number , z?: number ): number { if (typeof z === 'number' ) { return x + y + z } else { return x + y } }
而在可選參數後面不可以再添加確定參數
例外說明:引數預設值
在 ES6 中,我們允許給函式的引數新增預設值,TypeScript 會將添加了預設值的引數識別為可選引數:
1 2 3 4 5 function buildName (firstName: string , lastName: string = 'Cat' ) { return firstName + ' ' + lastName; } let tomcat = buildName ('Tom' , 'Cat' );let tom = buildName ('Tom' );
此時就不受「可選引數必須接在必需引數後面」的限制了:
1 2 3 4 5 function buildName (firstName: string = 'Tom' , lastName: string ) { return firstName + ' ' + lastName; } let tomcat = buildName ('Tom' , 'Cat' );let cat = buildName (undefined , 'Cat' );
例子三
1 2 3 4 5 6 7 8 9 10 11 const add = (x : number , y : number , z?: number ): number => { if (typeof z === 'number' ) { return x + y + z } else { return x + y } } const add2 : (x: number , y: number , z?:number ) => number = add
函式不只輸入、輸出有類型,本身也有類型
將 add2 賦予 string 會出錯誤
所以須聲明一模一樣的 const add2: (x: number, y: number, z?:number) => number = add
例子四
使用 interface (單純定義函式的 Interface)
1 2 3 4 5 6 7 8 const sum = (x: number , y: number ) => { return x + y } interface ISum { (x : number , y : number ): number } const sum2 : ISum = sum
1 2 3 4 5 6 7 8 interface SearchFunc { (source : string , subString : string ): boolean ; } let mySearch : SearchFunc ;mySearch = function (source: string , subString: string ) { return source.search (subString) !== -1 ; }
型別推論(Type Inference)\ 聯合型別(Union Types) \ 型別斷言(Type Assertion) 型別推論(Type Inference)
可以推論出我們賦值過程中,這個變數應該是什麼類型的
TS 會在沒有明確指定型別的時候,推測出型別
聯合型別(Union Types)
用分隔符號
當 TypeScript 不确定一个聯合型別的變數到底是哪個型別的时候,我们只能使用此聯合型別的所有型別裡共有的屬性或方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 let numberOrString : number | string numberOrString.length numberOrString.toString () function getLength (something: string | number ): number { return something.length ; }
聯合型別的變數在被賦值的時候,會根據型別推論的規則推斷出一個型別:
1 2 3 4 5 6 let numberOrString : string | number ;numberOrString = 'seven' ; console .log (numberOrString.length ); numberOrString = 7 ; console .log (numberOrString.length );
上例中,第二行的 numberOrString 被推斷成了 string,存取它的 length 屬性不會報錯。 而第四行的 numberOrString 被推斷成了 number,存取它的 length 屬性時就報錯了。
type guard
當遇到聯合類型,可以使用條件語句,自動幫你縮小型別範圍
1 2 3 4 5 6 7 8 function getLength2 (input: string | number ): number { if (typeof input === 'string' ) { return input.length } else { return input.toString ().length } }
型別斷言(Type Assertion)
開發者比 TS 更了解編寫的程式碼。因此,TS 允許開發者覆蓋它的推論,這樣的機制稱為「型別斷言」。
1 2 3 4 5 6 7 8 9 10 function getLength (input: string | number ): number { const str = input as string if (str.length ) { return str.length } else { const number = input as number return number .toString ().length } }
型別斷言不是型別轉換,斷言成一個聯合型別中不存在的型別是不允許的:
1 2 3 4 5 6 7 function toBoolean (something: string | number ): boolean { return <boolean >something; }
基礎型別先介紹到這裡,下篇將介紹一些進階用法~
資料來源:
線上課程:實戰 Vue3.0(正式版) + TS
TypeScript 新手指南