2017-08-02 64 views
0

我想擴展一個類並將其動態類型合併爲特定類型(從TPerson)。從泛型到特定類型

我已經創建僞類這個例子:

class Person { 
    constructor(public name: string){} 
} 

class Base<T> { 
    reference?: T 
    name: string 

    constructor(name: string) { 
     // Assign properties from T to this 
     this.name = name 
    } 

    static fromObject<T extends { name: string }>(object: T){ 
     const base = new Base(object.name) 
     base.reference = object 
     return base 
    } 
} 

class Master<T> extends Base<T> { 

    static fromBase<T>(base: Base<T>){ 
     const master = new Master(base.name) 
     master.reference = base.reference 
     return master 
    } 

    static fromObject<T extends { name: string }>(object: T){ 
     return Master.fromBase(Base.fromObject(object)) 
    } 
} 

class PersonMaster extends Master<Person> { 

    constructor(person: Person){ 
     super(person.name) 
     this.reference = person 
    } 

    static fromBase(base: Base<Person>){ 
     return new PersonMaster(base) 
    } 
} 

編譯器返回此錯誤:

類靜態側typeof PersonMaster錯誤地延伸的基類的靜態側typeof Master。財產類型fromBase不兼容。 (base: Base<Person>) => PersonMaster型不可分配到<T>(base: Base<T>) => Master<{}>。參數basebase的類型不兼容。 Base<T>型不可轉讓給Base<Person>。類型T不能分配給Person

回答

1

fromBaseMaster聲明是通用的:

static fromBase<T>(base: Base<T>) 

這是全稱量化:它說,fromBase應爲所有T工作。因此,當您嘗試將參數專用於PersonMaster時,類型檢查器正確地抱怨fromBase的這種實現不適用於所有T s,僅針對Person。重寫方法的類型參數必須與聲明方法的類型參數相匹配。

換句話說,在fromBase中聲明的T與封閉範圍中的T完全不同。它恰好掩蓋了這個名字。這可能是更容易理解,如果這兩個類型的參數有不同的名稱:

class Master<T> extends Base<T> { 
    static fromBase<U>(base: Base<U>) { /* ... */ } 
} 

在這種情況下,我懷疑你打算使用(剛性TMaster,而不是一個新鮮的(上位T。不幸的是,當你在你的評論中指出,你不能使用靜態方法來做到這一點,因爲TypeScript不支持它。 (我還沒有找到任何關於語言設計師爲什麼做出這個決定的文檔,我個人想不出有什麼好的理由,但我確定有這個理由。)所以你必須將你的方法移到對其他對象的實例方法:

interface MasterFactory<T> { 
    fromBase(base: Base<T>): Master<T> 
} 
class PersonMasterFactory implements MasterFactory<Person> { 
    fromBase(base: Base<Person>): Master<Person> { /* ... */ } 
} 
let personMasterFactory = new PersonMasterFactory(); 

有了這個設計,要求其將去PersonMaster.fromBase會去personMasterFactory.fromBase

重寫靜態方法首先是一件很奇怪的事情。方法重寫是基於接收方的類型動態調度調用,但是(至少在概念上)靜態方法沒有接收方。線索的名稱:動態分配靜態方法沒有意義!

+0

謝謝,下次使用時我會考慮到這一點,但它會給我'靜態成員不能引用類類型參數.'如果我沒有在函數定義中指定'T',錯誤 – Akxe

+0

我沒有知道關於靜態成員。看起來像是TypeScript設計師的疏忽,儘管我確信它有一個很好的理由。無論如何,我認爲你有一個設計問題:重寫靜態成員是一件很奇怪的事情。重寫是一種固有的動態行爲,所以如果某些東西需要被重載,你應該把它作爲一個實例屬性 - 換句話說,提取一個'MasterFactory'類 –

+0

我應該在typescript GitHub上寫一個問題嗎?爲什麼重寫靜態方法很奇怪,爲什麼使用工廠呢?並編輯你的答案,因爲它不幸是不正確的。 – Akxe