從開始學習前端之後,大多的學習資源都是來自線上課程、youtube 影片為主,鮮少透過閱讀書籍來學習相關知識,但自從進入公司之後,因為公司內有些程式書籍能夠借閱,先是從 JavaScript 大全開始,一開始閱讀起來真的滿痛苦,不知道該如何消化內容,直接順著讀過去又怕忘記,但目前還是順順的讀到了第8章~後來,找到的方式就是在筆記軟體上做些註記,工作上遇到相關的再回過頭看一次,加入筆記。
而在此次,發現 TypeScript 即便已經看過介紹型別、基本使用基礎的影片後,仍然覺得不太足夠,所以就開始翻閱書籍 「讓 TypeScript 成為你全端開發的 ACE」,文中介紹滿多之前沒有注意到觀念、也有帶到不少 JavaScript 的觀念來呼應。所以本篇,多是來自於書中資訊,透過整理呈現。
註記 Annotation V.S. 斷言 Assertion
型別註記:指在告訴 TS 編譯器:「任何被註記到的變數、函式的參數等,都必須遵照被註記過後的變數型別」。
所以編譯器會隨時隨地的監測該變數有沒有出現型別衝突的可能—關鍵字為遵照。
而,斷言型別則是無視 TS 編譯器分析整個程式碼的型別推論過程,果斷的告訴 TS 編譯器:「被斷言過後的表達式之運算結果就是某某型別」—關鍵意象是「覆蓋」該表達式的型別推論結果。
註記與斷言
1 2 let randomNumber :number = Math .random ();const subscribed :boolean = true ;
如果遇到函式,參數(Argument)部分除了可以有類似註記方式標明輸入的參數型別外,在參數宣告結尾也可以註記該函式輸出之型別。
1 2 3 function isPositive (input: number ):boolean{ return input > 0 }
但JS裡,宣告函式的方法有很多種,其中一個是將函式最為值指派到變數。
1 2 3 const isPositive :(input:number ) => boolean = function (input ){ return input > 0 }
以上,也能把變數指派的函式,改成ES6箭頭函式
指派運算子(Assignment Operator ,就是指程式裡的等號)左方是函式的型別註記表示法,右方則是普通函式宣告
1 const isPositive :(input:number ) => boolean = input => input >0 ;
1 2 3 const isPositive = function (input:number ):boolean { return input>0 }
1 2 const isPositive = (input :number ):boolean => input>0
型別斷言語法
斷言(Assertion)的語法很簡單,看到有使用關鍵字 as 或者 <T>(...) 的格式就是斷言的用法。
通常會使用斷言的情境,程式沒辦法推論某表達式的確切運算結果之型別,我們才會用選擇使出斷言來處理這種情境。
程式沒辦法推論?
使用第三方的資源(Third-party resources),如使用外來JSON API 獲得的內容之型別格式、讀取檔案轉成 JSON 物件的結果、使用套件提供的功能、呼叫會回傳未知結果的函式。
1 const aNumber = returnsUnknow () as number ;
或是這樣:
1 const aNumber = <number >(returnsUnkonw ());
請注意:斷言的語法部分,沒有人斷言在變數的名稱宣告部分—也就是是說,如果你這樣寫是錯的:
1 const aNumber as number = returnsUnknow ();
概念有點像,決斷地告訴程式,某表達式的運算結果之型別。
變數本身不是被運算,而是被指派某個東西,而斷言應該是斷在被指派的值或表達式的運算結果上。
複雜一點
函式宣告表達式有可以被斷言(畢竟函式作為表達式也會被當成值)
1 const isPositive =(input => input > 0 ) as (input : number ) => boolean
或者是:
1 const isPositive = <(input: number ) => boolean>(input => input >0 );
1 const isPositive :(input: number ) => boolean = input => input >0 ;
或者是
1 const isPositive =(input : number ):boolean => input >0 ;
說下,敘述式與表達式的定義與差別
敘述式:程式運行的流程,例如:JS 裡的判斷敘述式(if…else)以及迴圈敘述式(for 或者是 while 迴圈)。
表達式代表的則是程式碼運算的流程,並且會將運算結果回傳。其中兩者最關鍵差異為:敘述式不會回傳值,表達式則會。
1 2 3 4 5 6 7 8 9 10 1 +2 *3 ; true && (something === null || myAge < 18 ) Math .pow (2 ,10 ) myAge < 18 ? 'Youngster' : 'Adult' ;
而敘述式:
1 2 3 4 5 6 7 8 9 10 11 12 13 if (){ }else if (){ } else { } while (){ }
按照上面敘述式的定義 — 由於敘述式是在敘述運行流程,而不會回傳值,所以你才不會在 JavaScript 裡面看到這樣的寫法:
1 2 3 4 5 6 const status = if (Age <18 ){ return 'Young' }else { return 'Adult' }
注意:敘述式不一定是多行式(或區塊式)地呈現的最佳案例:變數宣告的指派敘述式(Variable Declaration Assignment Statement)
請問上面指派式會回傳什麼結果 =>數字 123 或 udefined。正解為 udefined
所以可以歸納出,javaScript 的變數宣告的指派式屬於敘述式,非表達式。
表達式什麼時候會以非單行的程式碼,也就是區塊的方式?
1 2 3 4 const status = (funcrion (myAge ){ if (myAge <18 ){ return 'Young' } return 'Adult' })(16 )
當可以分清楚表達式與敘述式差別後,回歸型別斷言
斷言的基礎語法
斷言的語法只能用在表達式上,因為表達式具備回傳值,敘述式則沒有
因此,可以「斷言該表達式所運算結果之代表型別」
寫法如下:
1 2 3 <expression> as T assertion <T assertion >(<expression>)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 (foo+bar*baz) as number ; (isPositive (num) && idEven (num)) as boolean ; Math .pow (2 , 10 ) as number (myAge <18 ? 'Young' : 'Adult' ) as string ; (funcrion (myAge ){ if (myAge <18 ){ return 'Young' } return 'Adult' })(16 ) as number somefunction (foo as number , bar as string ) as boolean
換種寫法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <number >(foo+bar*baz); <boolean > (isPositive (num) && idEven (num)) ; <number > Math .pow (2 , 10 ) ; <string >(myAge <18 ? 'Young' : 'Adult' ) ; <number >( funcrion (myAge ){ if (myAge <18 ){ return 'Young' } return 'Adult' })(16 ) ); <boolean >somefunction (foo as number , bar as string )
以上針對註記 Annotation V.S. 斷言 Assertion 做個簡單整理~