2017-02-01 92 views
1

TL; DR:我的函數接受構造函數或構造對象,然後對其進行變異,然後返回它。我怎樣才能正確地輸入返回值,以便類保持類,對象保持對象,並且都具有新屬性?鍵入可應用於類和實例的Typescript混合函數

詳細

我關閉:當混入對象,無論是原始的方法和混合的方法是可用的,當混合構造,唯一的方法混合可用。

兩個問題,我的當前的解決方案:

  1. 當混合在一個構造,所產生的實例的類型是MixinType & typof OriginalClass代替MixinType & OriginalClass(在OriginalClass靜態方法可作爲實例方法和實例方法不可用
  2. 當混合在一個構造,構造函數在其類型簽名沒有參數,它有MixinTypeClass構造函數簽名(這並不奇怪,這就是我寫的 - 這就是爲什麼我問這個問題,我是以另一種方式來做到這一點)。

我最好的嘗試

class OriginalClass { 
    instanceMethod(): void { } 
} 

interface MixinType { 
    mixedIn(): void; 
} 

interface MixinTypeClass<T> { 
    new(): MixinType & T; 
} 

function Mixin<T extends Function>(classOrInstance: T): MixinTypeClass<T>; 
function Mixin<T extends Object>(classOrInstance: T): T & MixinType; 
function Mixin<T extends any>(classOrInstance: T): any { 
    if (typeof classOrInstance === 'function') { 
     (classOrInstance.prototype as any).mixedIn =() => { } 
     return classOrInstance as any as MixinTypeClass<T>; 
    } else { 
     (classOrInstance as any).mixedIn =() => { } 
     return classOrInstance as typeof classOrInstance & MixinType; 
    } 
} 

let NewClass = Mixin(OriginalClass); 
let instance1 = new NewClass(); 
instance1.mixedIn(); 
// Property 'instanceMethod' does not exist on the type 'MixinType & typeof OriginalClass' 
instance1.instanceMethod(); 

let instance2 = Mixin(new OriginalClass()); 
instance2.mixedIn(); 
instance2.instanceMethod(); 

那麼,怎樣才能更改Mixin,以便有針對instance1.instanceMethod()沒有編譯器錯誤?

回答

0

縮短您classOrInstance一個簡單arg, 你可以做如下:

function Mixin<T extends Object>(arg: Function): MixinTypeClass<T>; 
function Mixin<T extends Object>(arg: T): T & MixinType; 
function Mixin<T extends Object>(arg: Function | T): any { 
    if (arg instanceof Function) { 
     (arg.prototype as any).mixedIn =() => { } 
     return arg as MixinTypeClass<T>; 
    } else { 
     (arg as any).mixedIn =() => { } 
     return arg as T & MixinType; 
    } 
} 

這給全智能感知和類型安全:

let NewClass: MixinTypeClass<OriginalClass> = Mixin<OriginalClass>(OriginalClass); 
let instance1: OriginalClass & MixinType = new NewClass(); 
instance1.mixedIn(); 
instance1.instanceMethod(); 

let instance2: OriginalClass & MixinType = Mixin<OriginalClass>(new OriginalClass()); 
instance2.mixedIn(); 
instance2.instanceMethod(); 

這是有趣的是,MixinTypeClass<OriginalClass>OriginalClass & MixinType是不一樣的。

相關問題