2016-11-14 51 views
0

給定一個JavaScript庫的以下環境類型定義(即我不能改變):如何更改/擴展屬性的類型?

// a library with typings I cannot change 
interface Widget { 
    name: string; 
} 
interface Event { 
    widget: Widget; 
} 

declare function addListener(listener: (event: Event) => void):void; 
declare function showWidget(renderFn: (widget: Widget) => void): void; 

還有通過這樣的事情是一個擴展模塊的JavaScript庫,增強event.widget(但不是一般的窗口小部件) ;

interface EnhancedWidget { 
    displayName: string; 
} 
function eventExtender(event:Event) { 
    (event.widget as any).displaName = '....'; 
} 

現在我要增強Event這一定義,但打字稿抱怨

interface Event { 
    widget: Widget & EnhancedWidget; 
} 

添加新的特性允許,但更改屬性的類型是不允許的。但這是現實中可能發生的事情。我想知道是否有辦法在打字稿中表達這一點。

最後我想用event.widgetdisplayName屬性:

addListener(event => console.log(event.widget.displaName)) 

但這應該抱怨(因爲小部件是不是在這方面加強型):

showWidget(widget => console.log(event.displaName)) 

因此延長Widget像這樣是不是一個選項:

// does not work, because it will enhance all Widget usages and 
// not just in the specific context 
interface Widget { 
    displayName: string; 
} 

回答

0

如何有這些:

interface EnhancedWidget extends Widget { 
    displayName: string; 
} 
interface EnhancedEvent extends Event { 
    widget: EnhancedWidget; 
} 

,再加入另一個簽名addListener

declare function addListener(listener: (event: EnhancedEvent) => void):void; 

這仍然會失敗:

addListener(event => console.log(event.widget.displayName)); 

有了:

屬性「顯示名」的類型不存在「部件」

但是這將工作:

addListener((event: EnhancedEvent) => console.log(event.widget.displayName)) 
+0

的一點是,我沒有在庫(第一編碼塊)控制。在該庫中有許多'addListener'類似的函數,我不想重寫外部庫的所有類型。 –

+0

啊,我明白這是如何在這個特殊情況下起作用的。不過,我必須知道在回調中使用'EnhancedEvent'。我正在尋找一種代碼完成的方式告訴我,'event.widget'現在具有新的屬性。 –

+0

我不認爲這是可能的。使用'EnhancedEvent'只是正常的多態性。使用新類型是有道理的,因爲您確實不會更改所有事件/小部件的實例,而只是那些獲得「增強」的實例。 –