381 Stimmen

Typescript - Objekt klonen

Ich habe eine Superklasse, die das Elternelement (Entity) für viele Unterklassen (Customer, Product, ProductCategory...) ist

Ich möchte in Typescript dynamisch ein Objekt klonen, das verschiedene Teilobjekte enthält.

Zum Beispiel: ein Customer, der verschiedene Product enthält, die eine ProductCategory haben

var cust:Customer = new Customer();

cust.name = "someName";
cust.products.push(new Product(someId1));
cust.products.push(new Product(someId2));

Um den gesamten Objektbaum zu klonen, habe ich eine Funktion in Entity erstellt

public clone():any {
    var cloneObj = new this.constructor();
    for (var attribut in this) {
        if(typeof this[attribut] === "object"){
           cloneObj[attribut] = this.clone();
        } else {
           cloneObj[attribut] = this[attribut];
        }
    }
    return cloneObj;
}

Der new Fehler tritt auf, wenn er zu Javascript transpiliert wird: Fehler TS2351: Kann 'new' nicht mit einem Ausdruck verwenden, dessen Typ über eine Aufruf- oder Konstruktions-Signatur verfügt.

Obwohl das Skript funktioniert, möchte ich den transpilierten Fehler loswerden

1voto

Cvassend Punkte 125

Zusatz für Option 4 von @fenton, mit angularJS ist es ziemlich einfach, eine Deep Copy eines Objekts oder Arrays mit folgendem Code zu erstellen:

var deepCopy = angular.copy(objectOrArrayToBeCopied)

Weitere Dokumentationen finden Sie hier: https://docs.angularjs.org/api/ng/function/angular.copy

0voto

patrickbadley Punkte 2380

Ich habe versucht, einen generischen Kopier-/Klon-Service zu erstellen, der Typen für verschachtelte Objekte beibehält. Würde gerne Feedback erhalten, wenn ich etwas falsch mache, aber es scheint bisher zu funktionieren...

import { Injectable } from '@angular/core';

@Injectable()
export class CopyService {

  public deepCopy(objectToClone: T): T {
    // Wenn es sich um einen einfachen Typ oder null handelt, einfach zurückgeben.
    if (typeof objectToClone === 'string' ||
      typeof objectToClone === 'number' ||
      typeof objectToClone === 'undefined' ||
      typeof objectToClone === 'symbol' ||
      typeof objectToClone === 'function' ||
      typeof objectToClone === 'boolean' ||
      objectToClone === null
    ) {
      return objectToClone;
    }

    // Andernfalls prüfen, ob es einen Konstruktor gibt, den wir verwenden können, um ihn ordnungsgemäß zu instanziieren...
    let ctor = Object.getPrototypeOf(objectToClone).constructor;
    if (ctor) {
      let clone = new ctor();

      // Sobald wir den richtigen Typ instanziiert haben, weisen wir den Kind-Eigenschaften tiefe Kopien der Werte zu
      Object.keys(objectToClone).forEach(key => {
        if (Array.isArray(objectToClone[key]))
          clone[key] = objectToClone[key].map(item => this.deepCopy(item));
        else
          clone[key] = this.deepCopy(objectToClone[key]);
      });

      if (JSON.stringify(objectToClone) !== JSON.stringify(clone))
        console.warn('Objekt geklont, passt aber nicht genau zusammen...\nObjekt: ' + JSON.stringify(objectToClone) + "\nKlon: " + JSON.stringify(clone))

      // gibt unser geklontes Objekt zurück...
      return clone;
    }
    else {
      // bin mir nicht sicher, ob das jemals erreicht wird, aber ich dachte, ich hätte eine Auffangfunktion.
      console.log('Deep Copy hat etwas gefunden, das es nicht kannte: ' + JSON.stringify(objectToClone));
      return objectToClone;
    }
  }
}

0voto

alehro Punkte 2169

Was ist mit dem guten alten jQuery?! Hier ist eine tiefe Klonierung:

var clone = $.extend(true, {}, sourceObject);

0voto

Bernoulli IT Punkte 4798

Ich habe es am Ende gemacht:

public clone(): any {
  const result = new (this.constructor);

  // etwas Deserialisierungscode, den ich bereits hatte...
  // der alle serialisierten Eigenschaften des Objektgraphen tief kopiert
  // result.deserialize(this)

  // Sie könnten eine der Vorschläge in den anderen Antworten verwenden, um
  // alle gewünschten Felder/Eigenschaften zu kopieren

  return result;
}

Weil:

var cloneObj = new (this.constructor());

vom Benutzer @Fenton Laufzeitfehler verursachte.

Typescript-Version: 2.4.2

0voto

Pradeet Swamy Punkte 27
function instantiateEmptyObject(obj: object): object {
    if (obj == null) { return {}; }

    const prototype = Object.getPrototypeOf(obj);
    if (!prototype) {
        return {};
    }

    return Object.create(prototype);
}

function quickCopy(src: object, dest: object): object {
    if (dest == null) { return dest; }

    return { ...src, ...dest };
}

quickCopy(src, instantiateEmptyObject(new Customer()));

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X