天天看點

this類型_TypeScript筆記11

一.this也是一種類型!

其中,addclass與addclasses的類型簽名分别是:

傳回類型是this,表示所屬類或接口的子類型(稱之為有界多态性(f-bounded polymorphism)),例如:

上面的鍊式調用中,this類型能夠自動對應到所屬類執行個體類型上。沒錯,這種javascript運作時特性,在typescript靜态類型系統中同樣支援

具體地,typescript中的this類型分為2類:

class this type:類/接口(的成員方法)中的this類型

function this type:普通函數中的this類型

二.class this type

上例中的鍊式調用會正常執行,最後傳回b類執行個體。我們知道運作時this指向目前類或其子類執行個體,這在javascript運作時是一種非常常見的行為

也就是說,this的類型并不是固定的,取決于其調用上下文,例如:

class a中的this并不總是指向a類執行個體(也有可能是a的子類執行個體),那麼,應該如何描述this的類型?

this的類型

要給最初的場景添上類型描述的話,我們可能會這樣嘗試(如果沒有class this type):

意料之中的結果,foo(): a傳回a類執行個體,當然找不到子類b的成員方法。實際期望的是:

那麼,進一步嘗試:

b類中的this既是b類執行個體也是a類執行個體,姑且認為bar(): b & a是合适的,但無論如何foo(): a & b是不合理的,因為基類執行個體并不一定是子類執行個體……我們似乎沒有辦法給this标出一個合适的類型,尤其是在superthis.submethod()的場景

是以,針對類似的場景,有必要引入一種特殊的類型,即this類型:

this類型表現為所屬類/接口的子類型,這與javascript運作時的this值機制一緻,例如:

也就是說,this類型就是this值的類型:

實作原理

簡言之,就是把類/接口看作具有隐式類型參數this的泛型,并加上其所在類/接口相關的類型限制

具體的,this類型在實作上相當于a<this extends a<a>>(即經典的crtp 奇異遞歸模闆模式),類中this值的類型就是泛型參數this。出了目前類/接口的上下文,this的類型就是a<this: a>,類型相容性等與泛型一緻

是以,this類型就像一個帶有類派生關系限制的隐式類型參數

三.function this type

除了類/接口外,this類型還适用于普通函數

不同于class this type通常隐式發揮作用(如自動類型推斷),function this type大都通過顯式聲明來限制函數體中this值的類型:

把this顯式地作為函數的(第一個)參數,進而限定其類型,像普通參數一樣進行類型檢查。例如:

注意,僅在顯式聲明了this值類型時才進行檢查(如上例):

p.s.特殊的,箭頭函數(lambda)的this無法手動限定其類型:

與class this type的關聯

成員方法同時也是函數,兩種this類型在這裡産生了交集:

也就是說,成員方法中,如果沒提供function this type,那麼就沿用該類/接口的class this type,類似于自動推斷而來的類型與顯式聲明類型之間的關系:後者能夠覆寫前者

注意,雖然最初的設計是這樣的(開啟strictthis/strictthischecks選項),但由于性能等方面的原因,後來去掉了該選項。是以,目前function this type與class this type隐式檢查都很弱(比如未顯式指定this類型的成員方法并不預設具有class this type限制)

四.應用場景

流式接口(fluent interface)

this類型讓流式接口(fluent interface)變得很容易描述,例如:

p.s.所謂的流式接口(設計層面),可以簡單了解為鍊式調用(實作層面):

(摘自fluent interface)

簡言之,流式接口是oop中的一種api設計方式,通過鍊式方法調用讓源碼極具可讀性

描述this的類型

function this type允許我們像描述普通參數一樣限定this的類型,這在callback場景尤為重要:

(摘自this的類型)

追蹤context類型

有了this類型,bind、call、apply等場景也能正确維持類型限制,要求目前函數this與傳入的目标對象類型一緻:

讓類似的錯誤暴露出來(需要開啟strictbindcallapply選項):

p.s.關于bind、call、apply等類型限制的更多資訊,見strict bind, call, and apply methods on functions