Typescript 如何使用泛型类型和不同的构造函数扩展2个类?

Typescript 如何使用泛型类型和不同的构造函数扩展2个类?,typescript,Typescript,我遵循这个示例=> 在我的例子中,我想扩展一个main类=> export class MyClassOne { constructor(param1, param2) } 及 它可以工作,但我不知道如何设置泛型类型。因为如果我在这个范围内有任何东西,我会得到一个错误 “typeof MyClass2”类型的值不可调用。是吗 是指包含“新”吗 这是一个扩展泛型类的简单示例,与使用泛型类型进行多个扩展的方式相同,甚至与初始化或创建实例的方式相同: class BeeKeeper {

我遵循这个示例=>

在我的例子中,我想扩展一个main类=>

export class MyClassOne {
   constructor(param1, param2)
}

它可以工作,但我不知道如何设置泛型类型。因为如果我在这个范围内有任何东西,我会得到一个错误

“typeof MyClass2”类型的值不可调用。是吗 是指包含“新”吗


这是一个扩展泛型类的简单示例,与使用泛型类型进行多个扩展的方式相同,甚至与初始化或创建实例的方式相同:

class BeeKeeper {
    hasMask: boolean;
}

class ZooKeeper {
    nametag: string;
}

class Animal {
    numLegs: number;
}

class Bee extends Animal {
    keeper: BeeKeeper;
}

class Lion extends Animal {
    keeper: ZooKeeper;
}

function createInstance<A extends Animal>(c: new () => A): A {
    return new c();
}

createInstance(Lion).keeper.nametag;  // typechecks!
createInstance(Bee).keeper.hasMask;   // typechecks!
class养蜂人{
hassmask:布尔型;
}
动物园管理员{
nametag:string;
}
类动物{
numLegs:数字;
}
蜂类动物{
养蜂人:养蜂人;
}
狮子类动物{
饲养员:动物园饲养员;
}
函数createInstance(c:new()=>A):A{
返回新的c();
}
createInstance(Lion).keeper.nametag;//打字检查!
createInstance(Bee).keeper.hasMask;//打字检查!

您需要使用泛型来确保将原始类的类型转发到函数的输出。概述了这一模式

此代码将按预期工作,并在输出中保留所有类型参数

const addMyClassOneInheritance = <T extends new(...args: any[]) => any>(MyClassOne: T)=> {
    return class extends MyClassOne { };
}

class MyClassTwo<F extends string, O extends number>{
    constructor(param3: F, param4: O) { }
}
const MyFinalClass = addMyClassOneInheritance(MyClassTwo);

export class SynchMapComponent extends MyFinalClass<string, number> {
}


new SynchMapComponent("", 1)
const addmyclassoneheritation=any>(MyClassOne:T)=>{
返回类扩展MyClassOne{};
}
我的班级二{
构造函数(param3:F,param4:O){}
}
const MyFinalClass=addmyclassoneheritation(MyClassTwo);
导出类SynchMapComponent扩展MyFinalClass{
}
新的SynchMapComponent(“,1)

虽然mixin通常是一个非常好的概念,但我觉得它们并没有真正解决在一个类中扩展两个类的问题。相反,它们通过一组固定的额外功能增强了一个类。实际上,我认为不可能在一个类中扩展两个不同的、不相关的类。但假设我们接受两个小的住宿,我们可以非常接近:

  • 因为原型链是线性的,所以扩展类的实例只能是它的一个anchestor(比方说第一个)的
    instanceof
  • 由于TypeScript类只能实现具有静态已知成员(且没有泛型类型变量)的接口,因此不可能创建一个
    以泛型方式扩展另外两个类。我们将改为工厂函数
  • 现在,看一下以下函数:

    type Constructable = new (...args: any[]) => any;
    
    const mergeClasses = <S extends Constructable, T extends Constructable>(class1: S, class2: T) =>
        <Si extends InstanceType<S> = InstanceType<S>, Ti extends InstanceType<T> = InstanceType<T>>
        (args1: ConstructorParameters<S>, args2: ConstructorParameters<T>): Si & Ti => {
            const obj1 = new class1(...args1);
            const obj2 = new class2(...args2);
            for (const p in obj2) {
                obj1[p] = obj2[p];
            }
            return obj1 as Si & Ti;
        };
    
    您只需编写以下内容(如果类型参数不是泛型的,则省略它们):

    const instanceFactory=mergeClasses(MyClassOne,MyClassTwo);
    const instance=instanceFactory([1,2],[3,4]);
    

    您也可以查看示例代码。

    可能重复@rannieaguilarperata是的,谢谢。。。这正是我在第一行发布的链接。。。。我会编辑这个名字,这样即使人们不点击,他们也会知道…@Bobby你能提供一个更完整的例子来说明你想要实现什么吗?您发布的错误与代码无关(
    synchronizationRelation
    未出现在发布的代码中)。为了得到一个答案,一个最小的自我包含的方式来重现你的问题将有帮助是的抱歉,我更改了命名以使其更清楚,并且忘记了更改错误:=>MyClassTwoyes,但是如果有双重继承,那么动物,但是,然后有一个Lion wich扩展了这两个类?我认为您需要创建一个公共接口,并为扩展这两个类的接口创建一个实例,这样您的Lion类将同时使用这两个类
    const addMyClassOneInheritance = <T extends new(...args: any[]) => any>(MyClassOne: T)=> {
        return class extends MyClassOne { };
    }
    
    class MyClassTwo<F extends string, O extends number>{
        constructor(param3: F, param4: O) { }
    }
    const MyFinalClass = addMyClassOneInheritance(MyClassTwo);
    
    export class SynchMapComponent extends MyFinalClass<string, number> {
    }
    
    
    new SynchMapComponent("", 1)
    
    type Constructable = new (...args: any[]) => any;
    
    const mergeClasses = <S extends Constructable, T extends Constructable>(class1: S, class2: T) =>
        <Si extends InstanceType<S> = InstanceType<S>, Ti extends InstanceType<T> = InstanceType<T>>
        (args1: ConstructorParameters<S>, args2: ConstructorParameters<T>): Si & Ti => {
            const obj1 = new class1(...args1);
            const obj2 = new class2(...args2);
            for (const p in obj2) {
                obj1[p] = obj2[p];
            }
            return obj1 as Si & Ti;
        };
    
    class MyClassOne {
        constructor(param1: number, param2: number) { }
    }
    
    class MyClassTwo<F, O> {
        constructor(param3: number, param4: number) { }
    }
    
    const instanceFactory = mergeClasses(MyClassOne, MyClassTwo);
    const instance = instanceFactory<MyClassOne, MyClassTwo<number, string>>([1, 2], [3, 4]);