Typescript 在node.js中将mixin与泛型组合
我正在开发一个库,我希望为相同的库方法支持一些不同的扩展。Typescript 在node.js中将mixin与泛型组合,typescript,generics,mixins,Typescript,Generics,Mixins,我正在开发一个库,我希望为相同的库方法支持一些不同的扩展。 以下是我的简短混音代码,仅供您参考: type Creator<T = {}> = new (...args: any[]) => T; class DefaultCreator { world:string[] = []; someMagic() { this.world.push("magic") } getWorldList(
以下是我的简短混音代码,仅供您参考:
type Creator<T = {}> = new (...args: any[]) => T;
class DefaultCreator {
world:string[] = [];
someMagic() {
this.world.push("magic")
}
getWorldList() {
return this.world;
}
}
function PlantCreator<TBase extends Creator>(Base: TBase) {
return class extends Base {
private world = (<DefaultCreator><any>this).world;
createPlant() {
this.world.push("Plant")
}
};
}
function AnimalCreator<TBase extends Creator>(Base: TBase) {
return class extends Base {
private world = (<DefaultCreator><any>this).world;
createDog() {
this.world.push("Dog")
}
};
}
我现在的问题是,如何创建一个从上面获取“MyWorld”的类
abstract class Playground {
abstract createWorld(creator: DefaultCreator);
play() {
this.createWorld(new DefaultCreator());
}
}
我的想法是,实现可以使用框架特性(这里只需播放)并使用定制的创建者(aka Builder)创建世界。我尝试了泛型,但无法编译。我做错了什么?这似乎是不可能的。因为
MyWorld
不是一个类型,它更像是一个奇怪的类型描述
当我让我的想法指定类型时,我得到这一行:
const MyWorld: { new(): ({ world: string[]; createDog(): void } & any); prototype: { world: string[]; createDog(): void } } = AnimalCreator(PlantCreator(DefaultCreator));
我的解决方案是按约定强制用户创建实例,并返回示例的世界
我修改了我的游乐场,以便获得以下代码:
abstract class Playground {
abstract createWorld(): string[];
play() {
console.log("Creating world containing:");
this.createWorld().forEach(item => console.log(`- ${item}`))
}
}
class MyPlayground extends Playground {
createWorld(): string[] {
const world = new MyWorld();
world.someMagic();
world.createPlant();
world.createDog();
return world.getWorldList();
}
}
new MyPlayground().play();
上述代码的输出:
创建包含以下内容的世界:
-魔法
-植物
-狗
这似乎是不可能的。因为MyWorld
不是一个类型,它更像是一个奇怪的类型描述
当我让我的想法指定类型时,我得到这一行:
const MyWorld: { new(): ({ world: string[]; createDog(): void } & any); prototype: { world: string[]; createDog(): void } } = AnimalCreator(PlantCreator(DefaultCreator));
我的解决方案是按约定强制用户创建实例,并返回示例的世界
我修改了我的游乐场,以便获得以下代码:
abstract class Playground {
abstract createWorld(): string[];
play() {
console.log("Creating world containing:");
this.createWorld().forEach(item => console.log(`- ${item}`))
}
}
class MyPlayground extends Playground {
createWorld(): string[] {
const world = new MyWorld();
world.someMagic();
world.createPlant();
world.createDog();
return world.getWorldList();
}
}
new MyPlayground().play();
上述代码的输出:
创建包含以下内容的世界:
-魔法
-植物
-狗
事实上,你离这里不远,但是你模糊了类型和值之间的界限。幸运的是,Javascript/Typescript允许您这样做
//只匹配一个构造函数
类型Creator=new(…args:any[])=>T;
//匹配实际的类
接口创建者类{
新(…args:any[]):T;
}
类DefaultCreator{
世界:字符串[]=[];
神奇的东西{
这个。世界。推(“魔术”)
}
getWorldList(){
回归这个世界;
}
}
函数PlantCreator(基:TBase){
返回类扩展了基{
私人世界=(这个)世界;
createPlant(){
这个。世界。推动(“植物”)
}
};
}
功能动物创造者(基地:TBase){
返回类扩展了基{
私人世界=(这个)世界;
createDog(){
这个。世界。推(“狗”)
}
};
}
界面IPlantWorld{
createPlant():void;
}
IAnimalWorld接口{
createDog();
}
const MyWorld:CreatorClass=AnimalCreator(PlantCreator(DefaultCreator));
抽象班操场{
//我想要类的构造函数的引用
createOtherWorld(创建者:创建者){
返回新的创建者();
}
//我想引用类本身
createWorld(创建者:CreatorClass):T{
将新创建者()返回为T;
}
play(){
这个.createWorld(DefaultCreator);
}
}
班级一切游乐场工厂延伸游乐场{
play(){
//提供类型信息
返回这个.createWorld(MyWorld);
}
}
设pg=neweverythingplaygroundfactory();
让世界=pg.createWorld(MyWorld);
createPlant();
createDog();
pg.createOtherWorld(MyWorld.prototype.constructor);
这可能更符合您所寻找的内容
需要注意的是:
type Creator=new(…args:any[])=>T
只能引用任何类的实际构造函数,但永远不会匹配整个类/类对象。始终记住,类/函数是可执行对象。实际上,你离目标不远,但你模糊了类型和值之间的界限。幸运的是,Javascript/Typescript允许您这样做
//只匹配一个构造函数
类型Creator=new(…args:any[])=>T;
//匹配实际的类
接口创建者类{
新(…args:any[]):T;
}
类DefaultCreator{
世界:字符串[]=[];
神奇的东西{
这个。世界。推(“魔术”)
}
getWorldList(){
回归这个世界;
}
}
函数PlantCreator(基:TBase){
返回类扩展了基{
私人世界=(这个)世界;
createPlant(){
这个。世界。推动(“植物”)
}
};
}
功能动物创造者(基地:TBase){
返回类扩展了基{
私人世界=(这个)世界;
createDog(){
这个。世界。推(“狗”)
}
};
}
界面IPlantWorld{
createPlant():void;
}
IAnimalWorld接口{
createDog();
}
const MyWorld:CreatorClass=AnimalCreator(PlantCreator(DefaultCreator));
抽象班操场{
//我想要类的构造函数的引用
createOtherWorld(创建者:创建者){
返回新的创建者();
}
//我想引用类本身
createWorld(创建者:CreatorClass):T{
将新创建者()返回为T;
}
play(){
这个.createWorld(DefaultCreator);
}
}
班级一切游乐场工厂延伸游乐场{
play(){
//提供类型信息
返回这个.createWorld(MyWorld);
}
}
设pg=neweverythingplaygroundfactory();
让世界=pg.createWorld(MyWorld);
createPlant();
createDog();
pg.createOtherWorld(MyWorld.prototype.constructor);
这可能更符合您所寻找的内容
需要注意的是:
type Creator=new(…args:any[])=>T
只能引用任何类的实际构造函数,但永远不会匹配整个类/类对象。始终记住类/函数是可执行对象。您提供了一个有趣的解决方案。所以你在一个接口中放了一个构造函数来创建新的实例,对吗?如果这是真的:酷把戏!然而,您忽略了一个事实,即游乐场是一个抽象类,每个自定义实现都应该使用自己的创建者。当我修改createWorld
函数时,我无法使用PlantCreat中定义的方法