Javascript 为什么TypeScript无法识别mixin之间共享的属性?
我正在尝试在TypeScript中实现mixin 代码如下:Javascript 为什么TypeScript无法识别mixin之间共享的属性?,javascript,typescript,oop,inheritance,mixins,Javascript,Typescript,Oop,Inheritance,Mixins,我正在尝试在TypeScript中实现mixin 代码如下: type Mixable = new (...args: any[]) => {}; class Base { constructor(protected _a: string, protected _b: string) {} } const A = (Base: Mixable) => class A extends Base { a() { console.log(this._a); re
type Mixable = new (...args: any[]) => {};
class Base {
constructor(protected _a: string, protected _b: string) {}
}
const A = (Base: Mixable) => class A extends Base {
a() {
console.log(this._a);
return this;
}
};
const B = (Base: Mixable) => class B extends Base {
b() {
console.log(this._b);
return this;
}
};
const C = A(B(Base));
const o = new C("a","b");
o.a().b();
但不幸的是,编译器无法识别mixin、chain方法和发出的错误之间共享的属性
另外,如果您运行此程序,它将成功运行,并生成预期的输出,而不会出现任何JS错误。为了访问属性
\u a
和\u b
,您需要强制应用mixin的类具有这些属性
另外,在带有保护的属性的typescript中,混入可能会很棘手,所以我将它们设置为公共的
interface HasAB {
_a: string;
_b: string;
}
type Mixable = new (...args: any[]) => HasAB
class Base {
constructor(public _a: string, public _b: string) {}
}
interface AB {
a: string;
b: string;
}
这就解决了访问属性的问题
编辑:
我一直在玩这个游戏,不幸的是,混入只是为了不适合非公共属性。使用组合类可以访问传入类的受保护属性,但它们会给我们错误TS4094“导出类表达式的属性\u a”可能不是私有的或受保护的。”因为mixin的属性必须是公共的
我没有足够的信心说这是不可能的,但是如果我是你,我会考虑不同的设计模式。您可以将访问器方法getA()
和getB()
添加到类Base
。或者您可以定义readonly public
属性a
和b
,这些属性访问底层私有属性\u a
和\u b
下面是第二个案例的分解:
我们定义了一个接口AB
,它具有public
属性a
和b
。回想一下,typescript接口中的所有属性本质上都是公共的
interface HasAB {
_a: string;
_b: string;
}
type Mixable = new (...args: any[]) => HasAB
class Base {
constructor(public _a: string, public _b: string) {}
}
interface AB {
a: string;
b: string;
}
我们声明,如果可以使用关键字new
创建is,并且所创建的对象具有a
和b
,则认为某个对象是可混合的
type Mixable = new (...args: any[]) => AB;
我们修改Base
,使其实现接口AB
,这将使其可混合。您可以显式地编写类基类实现AB
,但不必这样做。只要它可以读取属性a
和b
,它就可以分配给Mixable
。我们使用javascript getter将a
和b
实现为只读
属性,这些属性将读取\u a
和\u b
的私有值,但不能修改它们
class Base {
constructor( protected _a: string, protected _b: string) {}
get a(): string {
return this._a;
}
get b(): string {
return this._b;
}
}
现在是我们的混音。我们说要混合的类必须是Mixable
类型。我们使用泛型(Mixed:T)
,这样我们就知道返回的类将拥有传入类的所有属性和方法,而不仅仅是mixeable
中的属性和方法。这解决了链接的问题
请注意,我重命名了您示例中的方法,因为我使用了a
和b
作为属性的名称,所以我不能将它们也用作方法的名称
const A = <T extends Mixable>(Mixed: T) => class A extends Mixed {
aMethod() {
console.log(this.a);
return this;
}
};
const B = <T extends Mixable>(Mixed: T) => class B extends Mixed {
bMethod() {
console.log(this.b);
return this;
}
};
谢谢大家的贡献。这给这个问题增加了巨大的价值
在我继续之前,让我解释一下我的初衷以及我的代码引起的误解
我使用mixin的主要目标是分解我的大型类。因为这将应用于不同的类,所以我正在创建一个帮助器模块。为了使示例易于理解,我发布了一个更简单的实现
关于Base
标识符,我的意思不是Base
参数指的是基类,而是父类(即扩展的基)。无论如何,为了消除混淆,我将使用标识符Parent
所以,这里是我提出的,我相信它是非常可扩展的。请忽略这个奇怪的名字Libbable
(这只是为了说明这个想法)
类型Mixable=new(…args:any[])=>T;
接口libable{
x:字符串;
a():任何;
}
类型Mixin=可混合;
类库{
构造函数(公共x:string){}
a():this{返回this}
}
常量A=(父级:T)=>类扩展父级{
(){
console.log(this.x);
归还这个;
}
};
常量B=(父级:T)=>类扩展父级{
b(){
返回这个.a();
}
};
常数L=A(B(Lib));
常数o=新的L(“x”);
o、 a().b();
因为,目前,TypeScript无法在mixin之间共享非公共属性。我真的很期待能够使用它,否则,强大的访问修饰符在这里就毫无用处了
由于有必要在基类中声明方法以在mixin中使用它们,因此一旦调用mixin的适用类方法,就会调用它们。这不是我想要的。JS允许我们去掉这个,但是TS没有。如果你有更好的想法来实现我想要的,请随意分享。const a=(Base:Mixable)=>class a扩展了Base
-“Base”与class Base
没有关系,它只是mixins@AlekseyL上的Mixable
文档类型的参数Base
作为参数传递给mixin生成器,Base
中可用的属性在a
和B
中也可用。请随意查看JS实现。非常感谢您的贡献。但最终基类将具有受保护的属性,并且只要mixin继承了基类,就应该能够访问这些属性,而且它还应该支持方法链接。要么TypeScript还不能实现,要么我找不到解决方法。protected的问题是我们需要TypeScript了解我们的Mixable类必须有属性a和b,并且TypeScript接口成员被认为是公共的。也许有办法解决这个问题,我只是不知道。我知道如果混音是