做者:Marius Schulz
譯者:前端小智
來源: https://mariusschulz.com/
點贊再看,養成習慣本文
GitHub
https://github.com/qq44924588... 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。前端
null
/undefined
在TypeScript 2.2中,空檢查獲得了進一步的改進。TypeScript 如今將帶有可空操做數的表達式標記爲編譯時錯誤。git
具體來講,下面這些會被標記爲錯誤:github
+
運算符的任何一個操做數是可空的,而且兩個操做數都不是any
或string
類型。-
,*
,**
,/
,%
,<<
,>>
,>>>
, &
, |
或 ^
運算符的任何一個操做數是可空的。<
,>
,<=
,>=
或 in
運算符的任何一個操做數是可空的。instanceof
運算符的右操做數是可空的。+
,-
,~
,++
或者--
的操做數是可空的。來看看若是我們不當心,可空表達式操做數就會坑下我們的狀況。在 TypeScript 2.2 以前,下面這個函數是能夠很好地編譯經過的:面試
function isValidPasswordLength( password: string, min: number, max?: number ) { return password.length >= min && password.length <= max; }
注意,max
參數是可選的。這意味着我們可使用兩個或三個參數來調用isValidPasswordLength
:typescript
isValidPasswordLength("open sesame", 6, 128); // true isValidPasswordLength("open sesame", 6, 8); // false
密碼 "open sesame"
的長度爲10
個字符。所以,對於長度範圍 [6,128]
返回 true
,對於長度範圍[6,8]
返回false
,到目前爲止,一切 ok。express
若是調用isValidPasswordLength
且不提供max
參數值,那麼當密碼長度超過 min
值時,我們可能但願返回 true
。然而,事實並不是如此:segmentfault
isValidPasswordLength("open sesame", 6); // false
這裏的問題在於 <= max
比較。若是max
是 undefined
,那麼 <= max
的值永遠都爲false
。在這種狀況下,isValidPasswordLength
將永遠不會返回true
。框架
在 TypeScript 2.2 中,表達式password.length <= max
是不正確的類型,若是你的應用程序正在嚴格的null
檢查模式下運行:函數
function isValidPasswordLength( password: string, min: number, max?: number ) { return password.length >= min && password.length <= max; // Error: 對象可能爲「未定義」. }
若是操做數的類型是null
或undefined
或者包含null
或undefined
的聯合類型,則操做數視爲可空的。注意:包含
null
或undefined
的聯合類型只會出如今--strictNullChecks
模式中,由於常規類型檢查模式下null
和undefined
在聯合類型中是不存在的。工具
那麼要怎麼修正這個問題呢?一種的解決方案是爲max
參數提供一個默認值,它只在傳遞undefined
時起做用。這樣,該參數仍然是可選的,但始終包含類型爲number
的值
function isValidPasswordLength( password: string, min: number, max: number = Number.MAX_VALUE ) { return password.length >= min && password.length <= max; }
固然我們也能夠選擇其餘的方法,可是我以爲這個方法很好。只要再也不將max
與undefined
的值進行比較,就能夠了
TypeScript 的一個目的是支持不一樣框架和庫中使用的通用 JS 模式。從TypeScript 2.2開始,增長了對 ES6 混合類(mixin class)模式。接下來說講 mixin
是什麼,而後舉例說明了如何在 TypeScript 中使用它們。
混合類是實現不一樣功能方面的類。其餘類能夠包含 mixin
並訪問它的方法和屬性。這樣,mixin
提供了一種基於組合行爲的代碼重用形式。
混合類指一個extends
(擴展)了類型參數類型的表達式的類聲明或表達式. 如下規則對混合類聲明適用:
extends
表達式的類型參數類型必須是混合構造函數.any[]
的變長參數, 而且必須使用展開運算符在super(...args)
調用中將這些參數傳遞。定義完成以後,來研究一些代碼。下面是一個 Timestamped
函數,它在timestamp
屬性中跟蹤對象的建立日期:
type Constructor<T = {}> = new (..args: any[]) => T; function Timestamped<TBase extends Constructor>(Base: TBase) { return class extends Base { timestamp = Date.now() } }
這看起來有點複雜,我們一行一行來看看:
type Constructor<T = {}> = new (..args: any[]) => T;
type Constructor <T>
是構造簽名的別名,該簽名描述了能夠構造通用類型T
的對象的類型,而且其構造函數接受任意數量的任何類型的參數。
接下來,讓咱們看一下mixin
函數自己:
function Timestamped<TBase extends Constructor>(Base: TBase) { return class extends Base { timestamp = Date.now(); }; }
Timestamped
函數接受一個名爲Base
的參數,該參數屬於泛型類型 TBase
。注意,TBase
必須與Constructor
兼容,即類型必須可以構造某些東西。
在函數體中,我們建立並返回一個派生自Base
的新類。這種語法乍一看可能有點奇怪。我們建立的是類表達式,而不是類聲明,後者是定義類的更經常使用方法。我們的新類定義了一個timestamp
的屬性,並當即分配自UNIX時代以來通過的毫秒數。
注意,從mixin
函數返回的類表達式是一個未命名的類表達式,由於class
關鍵字後面沒有名稱。與類聲明不一樣,類表達式沒必要命名。我們能夠選擇添加一個名稱,它將是類主體的本地名稱,並容許類引用本身
function Timestamped<TBase extends Constructor>(Base: TBase) { return class Timestamped extends Base { timestamp = Date.now(); }; }
如今已經介紹了兩個類型別名和mixin
函數的聲明,接下來看看如何在另外一個類中使用 mixin
:
class User { name: string; constructor(name: string) { this.name = name; } } // 經過將`"Timestamped"`混合到"User"中建立一個新類 const TimestampedUser = Timestamped(User); // 實例化新的 "TimestampedUser" 類 const user = new TimestampedUser("前端小智") // 如今,我們能夠同時從User 類中訪問屬性 // 也能夠從 Timestamped 類中訪問屬性 console.log(user.name); console.log(user.timestamp);
TypeScript 編譯器知道咱們在這裏建立並使用了一個mixin
,一切都是徹底靜態類型的,而且會自動完成和重構。
如今,看看一個稍微高級一點的 mixin
,類中定義一個構造函數
function Tagged<TBase extends Constructor>(Base: TBase) { return class extends Base { tag: string | null; constructor(...args: any[]) { super(...args); this.tag = null; } }; }
若是在混合類中定義構造函數,那麼它必須有一個類型爲any[]
的rest
參數。這樣作的緣由是,mixin
不該該綁定到具備已知構造函數參數的特定類;所以,mixin
應該接受任意數量的任意值做爲構造函數參數。全部參數都傳遞給Base
的構造函數,而後mixin
執行它的任務。在我們的例子中,它初始化 tag
屬性。
混合構造函數類型指僅有單個構造函數簽名,且該簽名僅有一個類型爲any[]
的變長參數,返回值爲對象類型. 好比, 有X
爲對象類型,new (...args: any[]) => X
是一個實例類型爲X
的混合構造函數類型。
之前面使用Timestamped
的相同方式來使用混合Tagged
:
// 經過 User 做爲混合 Tagged 來建立一個新類 const TaggedUser = Tagged(User); // 實例化 "TaggedUser" 類 const user = new TaggedUser("John Doe"); // 如今,能夠從 User 類訪問屬性和 Tagged 中的屬性 user.name = "Jane Doe"; user.tag = "janedoe";
到目前爲止,我們只在mixin
中添加了數據屬性。如今來看看另外一個 mixin
,它額外實現了兩個方法:
fucntion Activatable<TBase extends Constructor>(Base: TBase) { return class extends Base { isActivated = false; activate() { this.isActivated = true; } deactivate() { this.isActivated = false; } } }
我們從mixin
函數返回一個常規的類。這意味着我們可使用全部受支持的類功能,例如構造函數,屬性,方法,getter/setter
,靜態成員等。
如何所示,我們如何在 User
類中使用混合的 Activatable
:
const ActivatableUser = Activatable(User); // 實例化新的"ActivatableUser"類 const user = new ActivatableUser("John Doe"); //初始化,isActivated 的值爲 false console.log(user.isActivated); user.activate(); console.log(user.isActivated); // true
組合的mixin,可讓它更加靈活。一個類能夠包含任意多的mixin
,爲了演示這點,我們把上面提到的全部mixin
代碼組合在一塊兒。
const SpecialUser = Activatable(Tagged(Timestamped(User))); const user = new SpecialUser("John Doe");
固然 SpecialUser
類不必定很是有用,但關鍵是,TypeScript
靜態地理解這種mixin
組合。編譯器能夠類型檢查全部的使用,並在自動完成列表中建議可用的成員:
與類繼承進行對比,有個區別:一個類只能有一個基類。繼承多個基類在 JS 中不行的,所以在 TypeScript
中也不行。
原文:
https://mariusschulz.com/blog...
https://mariusschulz.com/blog...
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。
乾貨系列文章彙總以下,以爲不錯點個Star,歡迎 加羣 互相學習。
https://github.com/qq44924588...
我是小智,公衆號「大遷世界」做者,對前端技術保持學習愛好者。我會常常分享本身所學所看的乾貨,在進階的路上,共勉!
關注公衆號,後臺回覆福利,便可看到福利,你懂的。