使用继承的方法在深度克隆对象时保持精确键入

我的结构如下:


export class InteriorElement {

  private x: number;

  public draw(canvas: CanvasRenderingContext2D): void {

    throw Error('Draw Method not implemented yet');

  }

}


export class Seat extends InteriorElement {

  public draw(canvas: CanvasRenderingContext2D): void {

   canvas.drawRect(this.x, 0, 20, 20);

  }

}

我可以使用以下命令生成一个新对象:


const seat: Seat = new Seat();

seat.x = 5;

能用座位的抽奖方法


seat.draw(this.canvasContext);

现在,为了避免一遍又一遍地修改同一个座位,我想深入复制这个元素。但是,与其将方法复制/粘贴给每个孩子,我宁愿只使用IntersideElement类。因此,我希望有一个功能(我们非常邀请您改进该函数),如下所示:


public deepCopy(): InteriorElement {

  const deepCopy: InteriorElement = new InteriorElement(this.id);

  Object.keys(this).forEach((key: string) => {

    if (typeof (this[key]) === 'object') {

      return this.deepCopyObject(this[key]);

    } else {

      deepCopy[key] = this[key];

    }

  });

  return deepCopy;

}


private deepCopyObject(any: any): object {

  const deepCopy: object = new Object();

  Object.keys(any).forEach((key: string) => {

    if (typeof (any[key]) === 'object') {

      return this.deepCopyObject(any[key]);

    } else {

      deepCopy[key] = any[key];

    }

  });

  return deepCopy;

}

我现在可以使用一个简单的:


seat.deepCopy();

然而,问题在于这显然会返回一个InsideElement。所以这样做:


const seat2: Seat = seat.deepCopy();

seat2.draw(); 

将导致“绘制方法尚未实现”错误。即使const是键入的,它也会收到一个InsideElement,所以从现在开始它将是一个。


有没有办法为deepCopy提供泛型类型?像这样:


const seat2: Seat = seat.deepCopy<Seat>();

这将导致:


public deepCopy<T>(): T {

  const object: T = new T();

  [...]

}

不幸的是,它抛出了:“T”仅指一种类型,但在这里被用作值 - 错误。我如何知道InsideElement.deepCopy()副本请求哪个子项?


RISEBY
浏览 97回答 1
1回答

智慧大石

这里的核心问题是,您希望返回在超类上实现克隆函数,该超类返回正在复制的任何子类实例。首先,您需要返回类型 ,这意味着该方法返回与实例相同的类型。this其次,您希望调用与此类相同的构造函数。除非我弄错了,否则typescript不会让这变得容易。的类型只是 ,而不是您可能期望的类构造函数。但是,您可以以一种提供相当强大的类型安全性的方式强制使用它。someInstance.constructorFunctionclass A {&nbsp; constructor(public data: string) { }&nbsp; deepCopy<&nbsp; &nbsp; // This generic argument will be the type of the class object&nbsp; &nbsp; // that this is an instance of. It must be a subclass of A.&nbsp; &nbsp; T extends typeof A&nbsp; >(): this {&nbsp; &nbsp; // Get the constructor as the constructor of some subclass of A.&nbsp; &nbsp; const constructor = this.constructor as T&nbsp; &nbsp; // Create the new instance as the same type as `this`.&nbsp; &nbsp; const newInstance = new constructor(this.data) as this&nbsp; &nbsp; // return the copy.&nbsp; &nbsp; return newInstance&nbsp; }}class B extends A {}const b1 = new B('some data here')const b2: B = b1.deepCopy() // works操场泛型参数表示函数中将是某个构造函数,该构造函数是 A 的子类。我们真的不在乎哪一个。T extends typeof AT然后,我们可以简单地强制一些类型脚本无法推断的强制转换。但是,这种类型安全性崩溃的地方是,如果子类具有不同的构造函数签名,这可能会中断,因为不知道如何调用它们。deepCopy
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript