我正在尝试在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方法。
答案 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