2017-11-25 378 views
1

我認爲這是一個正確實現泛型的問題,但我不確定。如何從超類方法而不是超類類型返回子類型

我創建代表這裏的問題Github的要點是: https://gist.github.com/ORESoftware/66b72b4b85262d957cb03ad097e4743e

說我有這個超:

class A { 

    foo(): A { 
     return this; 
    } 

    } 

和幾個子類,一個例子看起來像這樣:

class B extends A { 

    bar(): B { 
     return this; 
    } 

    } 

所以如果我做

new B().foo().bar()

這將在運行時工作,但它不編譯與TypeScript。這是因爲foo()聲明返回類型爲A,而不是類型B

如何返回this的類型,而不是聲明foo()總是返回A

我嘗試這樣做:

enter image description here

,但我得到這個錯誤:

enter image description here

回答

1

你必須返回this使用polymorphic this type類型。

abstract class A { 
    foo(): this { 
     return this; 
    } 
} 

class B extends A { 
    bar(): this { 
     return this; 
    } 
} 

這將允許

const b = new B(); 

b.foo().bar(); 
+0

那麼我們有它,謝謝! –

1

我有兩個例子,一個具有過載和一個通用接口。

重載

如果你的意思是爲new C().foo().zoom()版本的工作,你可以做到這一點,同時還獲得一個關於bar()誤用下面的代碼,這將創建一個兼容的重載返回類型的子類型警告在父類:

class A { 
    foo(): A { 
    return this; 
    } 
} 

class B extends A { 
    foo(): B { 
    return this; 
    } 

    bar(): B { 
    return this; 
    } 
} 

class C extends A { 
    foo(): C { 
    return this; 
    } 

    zoom(): C { 
    return this; 
    } 
} 

const result = new C().foo().zoom(); 

如果在你的代碼的真正方法是確實要重複使用的東西,你可以調用super.foo() ......但在沒有需要的示例代碼。

foo(): C { 
    const a = super.foo(); 
    // You still need to return this, as it is a C, not an A. 
    return this; 
    } 

泛型

你不能讓基類的通用,爲了返回一個類型T。您不能將類用作其自己的類型參數的類型約束。 A也有問題,不能保證兼容T,延伸A

什麼你可能要做的是引入一個接口,並用它在每個類:

interface Fooable<T> { 
    foo(): T; 
} 

class A { 
    foo(): any { 
    return this; 
    } 
} 

class B extends A implements Fooable<C> { 
    bar(): B { 
    return this; 
    } 
} 

class C extends A implements Fooable<C> { 
    zoom(): C { 
    return this; 
    } 
} 

const result = new C().foo().zoom(); 
+0

這不是它的問題是,'FOO()'聲明其返回類型爲A'富():A',但我需要它可以是「this」的類型,可能是「B」或「C」,而不是「A」。 –

+0

我在這個問題上犯了一個錯誤,我糾正了它 - 我的意思是'new B()',而不是'new C()' –

+0

我會讓'A'成爲一個通用類來解決這個問題,但要做到這一點'需要具有'A類',並且不能將類用作其自己泛型類型參數的類型約束。 – Fenton