将泛型类型传递给Typescript

时间:2018-01-28 22:24:55

标签: typescript generics mixins

我正在尝试在Typescript中制作通用类型的mixins。我意识到,从版本2.8.0开始,Typescript还没有直接支持这个,issue #13979。我正在寻找一种解决方法。我不关心mixins本身有多丑,只要应用mixins是干净和可读的。

我需要一些mixin中的装饰器支持,所以我将mixins定义为嵌套类,模仿this helpful SO answer之后。更常见的方法returns class expressions instead。我还没有注意到在嵌套类方法中丢失任何功能。

我特别想要在外部mixin中指定的泛型类型来确定在更多嵌套混合中找到的类型,至少在外部mixin外部查看。我意识到可能需要一种更加截然不同的方法来处理Typescript可能无法通过嵌套函数调用传递外部函数中定义的类型的可能性。

给出以下代码:

interface ConcreteClass<C> { new (...args: any[]): C; }

class Entity {
    name = "base";
}

class Broker<E extends Entity> {
    static table = "entities";
}

interface BrokerType<E extends Entity> extends ConcreteClass<Broker<E>> {
    table: string;
}

class IdEntity extends Entity {
    id = 1;
}

function IdMixin<E extends IdEntity, B extends BrokerType<E>>(Base: B) {
    class AsIdBroker extends Base {
        constructor(...args: any[]) {
            super(...args);
        }
        getEntity(id: number): E | null {
            return null;
        }
    }
    return AsIdBroker;
}

class TaggedEntity extends IdEntity {
    tag = "gotcha";
}

这是理想的做法,但这不起作用:

// OPTION A -- broken

class TaggedBroker extends Broker<TaggedEntity> { };

class MyTaggedBroker extends IdMixin(TaggedBroker) {
    myStuff = "piled";
    showTag(id: number) {
        const entity = this.getEntity(id);
        if (entity) {
            // ERROR: Property 'tag' does not exist on type 'IdEntity'.
            console.log(entity.tag);
        }
    }
}

我也很乐意这样做,但这也不起作用:

// OPTION B -- broken

class TaggedBroker extends Broker<TaggedEntity> { };

// ERROR: Expected 2 type arguments, but got 1.
class MyTaggedBroker extends IdMixin<TaggedEntity>(TaggedBroker) {
    myStuff = "all mine";
    showTag(id: number) {
        const entity = this.getEntity(id);
        if (entity) {
            console.log(entity.tag);
        }
    }
}

这种最终方法使得所有当前代码都能正常工作,但除了冗长(至少使用我的应用程序中的名称)之外,它不会继承基本代理的类型,因此不是真正的混合:< / p>

// OPTION C -- works here, but drops types for any previously mixed-in brokers

class TaggedBroker extends Broker<TaggedEntity> { };

class MyTaggedBroker extends IdMixin<TaggedEntity, BrokerType<TaggedEntity>>(TaggedBroker) {
    myStuff = "all mine";
    showTag(id: number) {
        const entity = this.getEntity(id);
        if (entity) {
            console.log(entity.tag);
        }
    }
}

我发帖在这里以防有人知道我需要做什么。与此同时,我将继续探索我的选择,包括首先输入嵌套最多mixin的IoC方法。

1 个答案:

答案 0 :(得分:4)

要启用选项C以将成员从fn main() { let mut grid: [[i32; 10]; 10] = [[5; 10]; 10]; for (i, row) in grid.iter_mut().enumerate() { for (y, col) in row.iter_mut().enumerate() { //grid[i][y] = 7; print!("{}", col); } print!("{}","\n"); } } 继承到TaggedBroker,您只需进行一项简单的更改:

MyTaggedBroker

使用双调用方法可以实现对class TaggedBroker extends Broker<TaggedEntity> { public x: number; }; class MyTaggedBroker extends IdMixin<TaggedEntity, typeof TaggedBroker>(TaggedBroker) { myStuff = "all mine"; showTag(id: number) { console.log(this.x); const entity = this.getEntity(id); if (entity) { console.log(entity.tag); } } } 的更简洁的使用,其中在第一次调用中明确指定IdMixin,并且从参数值推断出E第二个电话:

B