【发布时间】:2018-07-07 14:26:58
【问题描述】:
我正在尝试在 Typescript 中制作通用类型的 mixin。我意识到,从开发版本 2.8.0 开始,Typescript 还没有直接支持这一点,每个 issue #13979。我正在寻找一种解决方法。我不在乎 mixins 本身有多丑陋,只要应用 mixins 是干净且可读的。
我需要一些 mixins 中的装饰器支持,所以我将 mixins 定义为嵌套类,模仿 this helpful SO answer。更常见的方法returns class expressions instead。我还没有注意到嵌套类方法中丢失了任何功能。
我特别想要一个在外部 mixin 中指定的泛型类型来确定在更多嵌套 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);
}
}
}
最后一种方法使所有当前代码都能工作,但除了冗长(至少在我的应用程序中的名称)之外,它不会继承基本代理的类型,因此不是真正的混合:
// 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 方法。
【问题讨论】:
-
所以选项 C 的问题是,如果您将成员添加到
TaggedBroker,它们不会被继承到MyTaggedBroker?
标签: typescript generics mixins