搜索词
mixin,构造函数参数
建议
允许mixin构造函数在剩余参数之前有参数,并推断mixin参数之间的组合。
用例
以下js代码是完全有效的且功能性的。然而,由于实际的mixin构造函数约束,我们无法在Typescript中重现此代码。
const mixin1 = (base) => class Mixin1 extends base {
constructor(m1v1, m1v2, ...args) {
super(...args);
this.m1v1 = m1v1;
this.m1v2 = m1v2;
}
};
const mixin2 = (base) => class Mixin2 extends base {
constructor(m2v1, m2v2, ...args) {
super(...args);
this.m2v1 = m2v1;
this.m2v2 = m2v2;
}
};
class Base {
constructor(v1, v2) {
this.v1 = v1;
this.v2 = v2;
}
}
class C1 extends mixin1(Base) {
}
class C2 extends mixin2(Base) {
}
class C3 extends mixin2(mixin1(Base)) {
}
console.log(new C1("m1v1", true, 1, {}));
console.log(new C2(false, 2, 1, {}));
console.log(new C3(false, 2, "m1v1", true, 1, {}));
示例
在ts中使用构造函数推断,相同的代码应该可以正常工作。
type Constructor = new (...args: any[]) => object;
const mixin1 = <T extends Constructor>(base: T) =>
class Mixin1 extends base {
m1v1: string;
m1v2: boolean;
constructor(m1v1: string, m1v2: boolean, ...args: any[]) {
super(...args);
this.m1v1 = m1v1;
this.m1v2 = m1v2;
}
}
const mixin2 = <T extends Constructor>(base: T) =>
class Mixin2 extends base {
m2v1: boolean;
m2v2: number;
constructor(m2v1: boolean, m2v2: number, ...args: any[]) {
super(...args);
this.m2v1 = m2v1;
this.m2v2 = m2v2;
}
}
class Base {
v1: number;
v2: object;
constructor(v1: number, v2: object) {
this.v1 = v1;
this.v2 = v2;
}
}
class C1 extends mixin1(Base) {
}
class C2 extends mixin2(Base) {
}
class C3 extends mixin2(mixin1(Base)) {
}
console.log(new C1("m1v1", true, 1, { })); // infer mixin1 and Base parameters: [string, boolean, number, object]
console.log(new C2(false, 2, 1, { })); // infer mixin2 and Base parameters: [boolean, number, number, object]
console.log(new C3(false, 2, "m1v1", true, 1, { })); // infer mixin2, mixin1 and Base parameters: [boolean, number, string, boolean, number, object]
检查清单
我的建议满足以下准则:
- 这不会对现有的TypeScript/JavaScript代码造成破坏性更改
- 这不会改变现有JavaScript代码的运行时行为
- 这可以在不根据表达式的类型发出不同的JS的情况下实现
- 这不是一个运行时特性(例如库功能,带有JavaScript输出的非ECMAScript语法等)
- 这个特性将与TypeScript's Design Goals的其他部分保持一致。
3条答案
按热度按时间x4shl7ld1#
编辑:也许需要更多的解释。
让我们考虑以下一组类,如下所示的“代码示例1”部分。
有3个持有者类,分别用于存储字符串、数字和Map。它们工作顺畅,如我们所见,派生类构造函数将子集或参数传递给每个派生类,这些选项对象是基类成员的超集。如果我们想要一个能够保留名称和标签的对象,那么我们必须从头开始实现,就像在“代码示例2”部分中那样。使用mixins来实现这种临时组合会很方便。让我们将INeedCount和INeedTags作为mixins并像在“代码示例3”部分中那样组合它们。
使用mixins轻松地通过具有多个参数或选项的多种构造函数扩展现有类,这将是非常棒的!
gg0vcinb2#
如果我理解正确的话,为了使这种类型的组合成为可能,mixin也应该知道基类的参数。是否可以通过泛型约束来实现。
这将是一个有趣的补充。
5us2dqdw3#
并非如此。我希望有选项来指定更严格的构造函数,即"...args: any[]"。你示例中的mixin有两个泛型参数。混合类的构造函数将是所需选项属性的交集加上泛型TOptions。
使用多个mixin的 Package 类看起来像洋葱,每一层消耗一个"& TOptions",并将其余部分传递下去。通常,你会用args皮肤传入的选项,最终的构造函数将获得定义的类型。我希望这相当清楚我的意思——否则我可以提供更详细的示例。