2017-11-25 380 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