打字稿泛型:类型' X'不能分配给' T'类型的参数。

时间:2017-09-06 07:03:57

标签: typescript

以下是一些打字稿代码:

class ClassA<T extends BlueItem = BlueItem> {

    protected _list: Array<T>;

    get list(): Array<T> {
        return this._list;
    }
}

class ClassB<T extends GreenItem = GreenItem> extends ClassA<T> {
    constructor() {
        super();
        this._list.push(new GreenItem());
    }
}

class BlueItem {
    protected blueItemProperty: number;
}


class GreenItem extends BlueItem {
    protected greenItemProperty: number;
}

编译器说&#34;类型&#39; GreenItem&#39;不能分配给&#39; T&#39;类型的参数。什么是解决这个问题的正确方法?

3 个答案:

答案 0 :(得分:2)

解决问题的一种简单方法是使列表项的构造函数也“通用”:

class ClassB<T extends GreenItem = GreenItem> extends ClassA<T>
{
  constructor(listItemCtor: {new(): T})
  {
    super();

    const t = new listItemCtor();

    this._list.push(t);
  }
}

它不是通用的解决方案 - 但如果适用的话 - 它会有所帮助。

作为一个选项,你也可以在基类中完全删除泛型:

class ClassA
{
    protected _list: Array<any>;
}

class ClassB<T extends GreenItem = GreenItem> extends ClassA
{
  constructor()
  {
    super();

    this._list.push(new GreenItem());
  }

  get list(): Array<T>
  {
    return this._list;
  }
}

由于您仍然对ClassB的公共属性进行类型检查,因此您不会失去太多。 _list是内部的。

答案 1 :(得分:1)

GreenItem投射到T

class ClassB<T extends GreenItem = GreenItem> extends ClassA<T> {
    constructor() {
        super();
        this._list.push(<T>new GreenItem());
    }
}

答案 2 :(得分:1)

问题是你不能在你的课程中生成正确的类型(T),因为你不知道T是什么。由于您不希望将工厂函数传递到您的类中,因此下一个最佳解决方案是使用联合类型并允许这两种类型,如下所示:

class ClassA<T = BlueItem> {

   protected _list:Array<T | BlueItem>;

   get list(): Array<T | BlueItem> {
    return this._list;
   }
}

class ClassB<T = GreenItem> extends ClassA<T | GreenItem> {
}

class ClassC extends ClassB<RedItem> {
}

但是,在这里您需要检查列表中的项目是否是正确的类型。