TypeScript版本: 2.2.0-dev.20170209
代码
要求mixin具有constructor(...args: any[])
构造函数签名会导致一些问题:
- Node v4是一个活跃的长期支持版本,但不支持rest和spread语法。我们避免使用它,即使针对ES6,也可以在Node v4上运行我们的输出。mixin构造函数要求防止这种情况。
- 通常会有希望提供特定构造函数的mixin。这些通常会最后应用以创建具体类。现在这是不可能的,所以你必须创建一个只有构造函数的新具体类,以给它正确的签名。
- 对于具有构造函数参数要求的mixin,从
...args
中提取参数非常繁琐。
以下是我遇到的一个例子。我有两个共享基类的类:
class Base {
foo: string[];
}
class A extends Base {}
class B extends Base {}
后来,我想通过mixins添加一些功能来创建两个新类:
type Constructor<T extends object> = new (...args: any[]) => T;
interface Magic {}
const Magic = <T extends Constructor<Base>>(superclass: T): Constructor<Magic>& T =>
class extends superclass implements Magic {
constructor(foo: string[]) {
super();
this.foo = foo;
}
};
const MagicA = Magic(A);
const MagicB = Magic(A);
我想让MagicA和MagicA具有接受单个参数的构造函数。我知道代码将起作用,因为我知道A和B的构造函数,但类型检查器不满意。
首先,在这种情况下Constructor
类型是错误的,因为我知道自己想要的签名。实际上,我希望写成这样:
type BaseConstructor = new() => Base;
type MagicConstructor = new(foo: string[]) => Magic;
interface Magic {}
const Magic = <T extends BaseConstructor>(superclass: T): MagicConstructor & T =>
class extends superclass implements Magic {
constructor(foo: string[]) {
super();
this.foo = foo;
}
};
const MagicA = Magic(A);
const MagicB = Magic(A);
预期行为:
这可以工作
实际行为:
错误:“类型'T'不是构造函数类型。”出现在扩展子句上。
5条答案
按热度按时间kqqjbcuj1#
在我看来,有很多使用场景。如果你需要一个灵活且功能丰富的mixin,你通常需要指定使用你的mixin的类的(构造函数)依赖关系。你希望将你的mixin限制在一组类中,例如控制器类,并希望访问像当前用户这样的属性,而不强制超状态包含这个属性。特别是如果mixin是从库中导入的,你真的不希望强制库的用户为了使用mixin而改变他的父类结构。
mcdcgff02#
+1 - 我的用例也是关于构造函数依赖注入的。我的混入限制了可能的基类,而那个基类有构造函数依赖。我希望强制混入的子类向构造函数提供正确的依赖项。就像常规(子)类一样。如果受限制的基类的构造函数签名发生变化,那么应该出现编译错误。
我目前使用以下解决方法:
使用这个解决方法,仅更改
MyBaseType
构造函数签名就可以得到编译错误(这就是我想要的)。然而,在更改MyBaseTypeConstructor
为正确签名后,不要忘记更改MyMixin
构造函数,因为在只更改MyBaseTypeConstructor
之后,你将不会再收到任何错误。那将是一个问题,因为MyMixin
的子类应该在这一点上导致编译错误。幸运的是,在更新MyMixin
内的构造函数后,你会得到剩余的错误,这些错误需要修复。dpiehjr43#
另一个模式(在JS中)是传递一个包含任何构造函数都可以读取的属性的
options
对象,而不考虑顺序。super()
调用栈中的任何构造函数都可以提取所需的内容。这很好,大多数情况下它只是工作得很好,只要层次结构中的所有类和mixin都使用单个
options
参数约定,并且不要在属性名称上发生冲突(这与示例属性/方法名称上的冲突问题相同,因此我们应该努力实现唯一命名)。csbfibhn4#
使用类型Assert,一切皆有可能😊。这对于mixin的用户来说效果很好(尽管编写mixin有点像黑魔法):
vngu2lb85#
@justinfagnani
关于相关问题,你在其他mixin中使用mixin时遇到过问题吗?似乎不起作用,在应用
___ is not a constructor function
mixin的extends
部分时,显示#32004。