【问题标题】:how to extend 2 classes with generic type and different constructor?如何使用泛型类型和不同的构造函数扩展 2 个类?
【发布时间】:2019-09-15 15:17:34
【问题描述】:

我正在关注这个例子 =>

Typescript: How to extend two classes?

就我而言,我想扩展一个主 class=>

export class MyClassOne {
   constructor(param1, param2)
}

MyClassTwo<F extends interface1, O extends interface2>{
        constructor(param3, param4)
}

所以我尝试了以下

const addMyClassOneInheritance = (MyClassOne : { new(...args) }) => {
  return class extends MyClassOne {};
}
const MyFinalClass = addMyClassOneInheritance(MyClassTwo);
export class SynchMapComponent extends MyFinalClass{

它有效,但我不知道如何设置我的泛型类型。因为如果我在 中有任何内容,我会收到错误

“typeof MyClassTwo”类型的值不可调用。你是否 是指包含“新”吗?

【问题讨论】:

  • @RannieAguilarPeralta 是的,谢谢...它正是我在第一行发布的链接...。然后我将编辑名称,因此至少即使人们不点击他们也会知道。 ..
  • @Bobby 你能提供一个更完整的例子来说明你想要实现的目标吗?您发布的错误与代码无关(SynchronizatorElement 未出现在发布的代码中)。要获得答案,重现您的问题的最小自包含方式将有所帮助
  • 是的,抱歉,我更改了命名以使其更清晰,但忘记更改错误:=> MyClassTwo

标签: typescript


【解决方案1】:

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

  1. 由于原型链是线性的,因此扩展类的实例只能是 instanceof 它的一个锚点(假设是第一个)。
  2. 由于 TypeScript 类只能实现具有静态已知成员的接口(并且没有泛型类型变量),因此无法创建 class 以泛型方式扩展其他两个。我们将改用工厂函数。

现在,看看下面的函数:

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;
    };

调用它将返回一个工厂函数,该函数构造对象实例,实现最初传递给mergeClasses 的两个类。例如扩展两个类

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]);

您也可以查看示例代码here

【讨论】:

    【解决方案2】:

    这是一个扩展泛型类的简单示例,您可以使用泛型类型进行多次扩展,甚至如何初始化或创建实例:

    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!
    

    【讨论】:

    • 是的,但是如果拥有双重继承,那么 Animal 还有 Mammalian 然后有一个 Lion 来扩展这两个类的展位?
    • 我认为您需要创建一个通用接口并为扩展这两个类的接口创建一个实例,以便您的 Lion 类将使用这两个类
    【解决方案3】:

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

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

    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)
    

    【讨论】:

      猜你喜欢
      • 2022-01-22
      • 2021-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多