TypeScript泛型:扩展类和接口

24

我有一个Typescript类,其中包含一个需要扩展另一个类并实现接口的泛型。 这是一个示例

interface IHasImage {
  imageUrl():string; 
}
class Model {
}
class View<T extends Model & IHasImage> {
}

我在其他地方看到过这种语法,但在Typescript中有没有一种方法可以做到这一点?

编辑: 尝试将以下内容粘贴到Playground中:http://www.typescriptlang.org/Playground

...[removed edit 1 code]

编辑2:答案和推理

对不起,第一个例子有一些缺陷! 我已经标记了正确的答案,尽管它可能需要一些提示,如此github问题所述(https://github.com/Microsoft/TypeScript/issues/1885)

给定以下代码,您可以看到方法论是有效的。

playground screenshot

唯一要说的是,试图从不扩展基类的类中实现接口也会失败。但是由于Typescript检查是基于对象结构的,如果您手动将name属性添加到类中,则会成功。

enter image description here

这也是为什么ModelCorrect可以成功扩展但不实现的原因。


我认为这个例子中有一个错误。构造函数中的“this”不是通用类型值。类应该有一个Model:T属性或构造函数可以接受一个value:T参数。 - Martijn
3个回答

31

Typescript不像Java或C#那么严格,因此您可以做类似于以下的事情:

interface IHasImage {
    imageUrl():string; 
}

class Model {
}

// use the Model class like an interface
interface IHasImageModel extends IHasImage, Model{
}

class View<T extends IHasImageModel> {
    constructor(arg :T){
       arg.imageUrl();
    }
}

编辑: 在TypeScript 1.6中,您可以使用交叉类型:

interface IHasImage {
    imageUrl():string; 
}

class Model {
}

class View<T extends IHasImage & Model> {
    constructor(arg :T){
       arg.imageUrl();
    }
}

1
class View<T> 实际上是什么意思? - SuperUberDuper
1
@SuperUberDuper 这是一个新的stackoverflow条目的问题。简而言之,这是一种用于泛型类的typescript方式。https://www.typescriptlang.org/docs/handbook/generics.html#generic-classes 您可以使用此类与符合“extens IHasImage&Model”要求的所有类型。 - Markus

14

看起来这是我能找到的唯一方法。虽然不完美干净,但它确实做了正确的事情。

interface IHasImage extends Model{  
  imageUrl():string; 
}

class Model {
}

class View<T extends IHasImage> {
}

这是一个在playground中验证其有效性的截图: playground 编辑:添加正确的解决方法。

我尝试过了,它确实编译通过了,但我认为它并没有我想要的效果,因为当我尝试执行 this.model.imageUrl() 时,它会抱怨 T 没有 imageUrl 函数。 - Dave Taylor
我会试一下,我觉得我尝试过了,但可能没有做。 - Dave Taylor
这几乎可以工作,它允许正确使用“model”属性,但出于某种原因,它不能限制为扩展基类的类... 我在GitHub上创建了一个问题,进一步解释了这个问题 https://github.com/Microsoft/TypeScript/issues/1885 - Dave Taylor
提供的示例存在严重问题。如果T需要扩展Model和实现IHasImage,则缺少实际的实现类。这将类似于class ModelWithImage extends Model Implements IHasImage {}在这种情况下,该类可以用作类型参数约束,或者可以添加一个其他接口。 - Martijn
这个答案的想法是正确的,这也是我标记它的原因,但是我在上面的编辑中添加了完整的解释(并修复了代码!...抱歉)。 - Dave Taylor

4

在这个例子中缺少的是T将会是什么:

下面的例子中,我添加了一个可以用作通用约束条件的T的实现。

interface IHasImage {
  imageUrl():string; 
}

class Model {
}

class ModelWithImage extends Model implements IHasImage {

    imageUrl():string
    {
     return "http://thepetwiki.com/images/thumb/Kitten.jpg/400px-Kitten.jpg";
    }   
}


class View<T extends ModelWithImage>
{
    value:T;

    constructor(arg:T)
    {   
        this.value=arg;
    }       
}

很不幸,这里的模型扩展太具体了,因为许多种类的模型可能具有相同的“IHasImage”功能。 - Dave Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接