2017-07-17 49 views
1

我嘗試將Polymer.dedupingMixin ES6函數轉換爲TypeScript。我不確定這是否可能。如何創建在TypeScript中返回mixin函數的函數?

https://github.com/Polymer/polymer/blob/v2.0.2/lib/utils/mixin.html

通常情況下,打字稿2.2+可以正確像下面的代碼基本混入功能工作。

type IConstructable = new (...args: any[]) => object; 
 

 
function extendClass<T extends IConstructable>(baseClass: T) { 
 
    return class extends baseClass { 
 
     instanceMethod_DynamicClass() { } 
 
     static staticMethod_DynamicClass() { } 
 
    } 
 
} 
 

 
class Test { 
 
    instanceMethod_TestClass() { } 
 
    static staticMethod_TestClass() { } 
 
} 
 

 
var d3 = extendClass(Test); 
 
d3.staticMethod_DynamicClass(); 
 
d3.staticMethod_TestClass(); 
 

 
var d4 = new d3(); 
 
d4.instanceMethod_DynamicClass(); 
 
d4.instanceMethod_TestClass();

我嘗試創建這樣的聲明機能的研究的一些功能。

declare function extendClass<T extends IConstructable>(baseClass: T): { 
 
    new (...args: any[]): { 
 
     instanceMethod_DynamicClass(): void; 
 
    }; 
 
    staticMethod_DynamicClass(): void; 
 
} & T;

我的打字稿代碼看起來像下面的代碼。它無法正常工作。我嘗試在許多地方修改泛型。但它仍然不起作用。

interface IConstructable<T> { 
 
    new(...args: any[]): T; 
 
} 
 

 
function extendClass<T extends IConstructable<T>, TExtended extends IConstructable<TExtended>>(mixin: (base: T) => TExtended & T) { 
 
    return function <T, TExtended>(base: T) { 
 
     return mixin(base); 
 
    }; 
 
} 
 

 
class Test { 
 
    instanceMethod_TestClass() { } 
 
    static staticMethod_TestClass() { } 
 
} 
 

 
class Test2 { 
 
    instanceMethod_TestClass() { } 
 
    static staticMethod_TestClass() { } 
 
} 
 

 
var propEffect = extendClass(superClass => {  
 
    return class internalClass extends superClass { 
 
     instanceMethod_ExtendedClass() { } 
 
     static staticMethod_ExtendedClass() { } 
 
    } 
 
}); 
 

 
var d3 = propEffect(Test) ; 
 
d3.staticMethod_ExtendedClass(); 
 
d3.staticMethod_TestClass(); 
 

 
var d4 = new d3(); 
 
d4.instanceMethod_ExtendedClass(); 
 
d4.instanceMethod_TestClass();

回答

1

我不明白爲什麼你需要extendClass(),因爲它基本上是恆等函數(它需要一個mixin作爲參數,並返回相同的行爲一個mixin),和你可以在代碼的其餘部分沒有錯誤執行這樣的:

function extendClass<M>(mixin: M): M { 
    return mixin; 
} 

假設你需要的extendClass()簽名明確表示,只接受混入,你可以這樣做。它有助於對混入一個類型別名:

type Mixin<X extends IConstructable<{}>> = <T extends IConstructable<{}>>(baseClass: T) => T & X; 

閱讀:一個Mixin<ExtendedClassConstructor>是一個函數,它接受一個通用的基類構造函數返回的東西這既是一個基類的構造函數和ExtendedClassConstructor。現在

可以實現extendClass()如下:

function extendClass<X extends IConstructable<{}>>(mixin: Mixin<X>): Mixin<X> { 
    return mixin; 
} 

不幸的是,現在打字稿不夠聰明,當你上的箭頭函數中調用extendClass()推斷的X類型。 X應該是internalClass,但由於它不在範圍內,所以不能引用它。您需要定義一個適當的類型,具有相同的形狀internalClass

type InternalClass = { 
    new(...args: any[]): { 
    instanceMethod_ExtendedClass(): void; 
    } 
    staticMethod_ExtendedClass(): void; 
} 

,然後你終於可以打電話extendClass(),小心鍵入箭頭功能一個mixin:

var propEffect = extendClass<InternalClass>(<T extends IConstructable<{}>>(superClass: T) => { 
    return class internalClass extends superClass { 
    instanceMethod_ExtendedClass() { } 
    static staticMethod_ExtendedClass() { } 
    } 
}); 

這應該都是與no errors一起工作,儘管我不確定它是否值得您購買。希望它能幫助你取得進步。

+0

感謝您的回答。我認爲你的解決方案几乎可行。不過,我需要寫兩次'internalClass'簽名。 –

+0

是的,我認爲這可能是你能做的最好的事情,因爲你需要引用一個外部範圍無法訪問的內部類。如果別人有更好的方法,我會有興趣看到它。 – jcalz

+0

混搭建築模式是怎麼回事?在TypeScript中可以做到嗎? (MyBaseClass).with(Mixin1,Mixin2){ http://justinfagnani.com/2015/12/21/real-mixins-with-javascript-classes/ –