流类型:如何键入动态类工厂

时间:2018-08-22 07:20:27

标签: javascript reactjs flowtype

我为模糊的标题预先表示歉意,但是我有一个问题要简洁地描述我的问题。

我有一个类Table,它带有一个动态Row类,该类将包装从类方法getRow()返回的行。我的问题是,如果不丢失getRow()返回的类型,就无法使其正常运行。

这是我到目前为止所拥有的:

// @flow

class Row {
    constructor() {}
};
class RowA extends Row {};
class RowB extends Row {};

class Table<RowType: Class<*>> {
    Row: RowType;

    constructor(RowClass: RowType = Row) {
        this.Row = RowClass;
    }

    getRow() {
        return new this.Row();
    }
};

const a = new Table(RowA);
(a.getRow(): RowA);

const b = new Table(RowB);
(b.getRow(): RowB);

const c = new Table();
(c.getRow(): Row);

演示在https://flow.org/try/#0PTAEAEDMBsHsHcBQiDG0CGBnToBKDQBvRUU0FWAO0wBcAnAVxRtjoAoBKIgX0W4G5UGbHgQBBUAFMAHjUmUAJjnzwegtFmUIAQlNnylo1YQHINIgCroARtEkAeFRYCeAB0kAuUAGFhmewBUAHxBRCRkKl5ObpKC4aQU1PRMLOwqvppRCC7uoAC8RlzEZCWgNAAWAJaYAHQq+UYZ2IIlvPGgAOaSNCqcYaVkdN0MdJSglJKqFdV1CJwtZLymqFS0oOgNE6pWtpJsKmIcgmzoNV09cxxZ8IdxiWvWm5OgO3b7OkeIbNZn3b1XRm0nxWSXIT22NjenzYKF+F3gnGuRyAA

及其返回的错误:

22: (a.getRow(): RowA);
     ^ Cannot cast `a.getRow()` to `RowA` because `RowB` [1] is incompatible with `RowA` [2].
References:
17:         return new this.Row();
                   ^ [1]
22: (a.getRow(): RowA);
                 ^ [2]
25: (b.getRow(): RowB);
     ^ Cannot cast `b.getRow()` to `RowB` because `RowA` [1] is incompatible with `RowB` [2].
References:
17:         return new this.Row();
                   ^ [1]
25: (b.getRow(): RowB);
                 ^ [2]

1 个答案:

答案 0 :(得分:1)

您必须使用声明的构造函数实现接口,或者使用(预定义的)构造函数扩展类。 RowInterfaceclass Rowclass Table的模板参数中可以互换。

我还为getRow()方法添加了类型。请另请参阅替代初始化(您不需要强制转换):

const a = new Table<RowA>(RowA);
let rA : RowA = a.getRow();

完整代码:

// @flow

interface RowInterface {
    constructor():void;
}

class Row implements RowInterface {
    constructor(){}
};

class RowA extends Row {
};
class RowB extends Row {
};

// bound to extend Row
//class Table<Entity: Row> { 
class Table<Entity: RowInterface> {
    _rowConstructor: Class<Entity>;

    // take a constructor
    constructor(row: Class<Entity>) {
        this._rowConstructor = row;
    }

    // return a constructed entity
    getRow(): Entity {
        return new this._rowConstructor();
    }
};


const a = new Table<RowA>(RowA);
let rA : RowA = a.getRow();

const b = new Table<RowB>(RowB);
(b.getRow(): RowB);