Das spezifische Problem lösen
Sie können eine Typassertion verwenden, um dem Compiler zu sagen, dass Sie es besser wissen:
public clone(): any {
var cloneObj = new (this.constructor() as any);
for (var attribut in this) {
if (typeof this[attribut] === "object") {
cloneObj[attribut] = this[attribut].clone();
} else {
cloneObj[attribut] = this[attribut];
}
}
return cloneObj;
}
Klonen
Ab 2022 gibt es einen Vorschlag, structuredClone
zu verwenden, um viele Typen tief zu kopieren.
const copy = structuredClone(value)
Es gibt einige Einschränkungen, auf welche Art von Objekten dies angewendet werden kann.
Beachten Sie, dass es manchmal besser ist, Ihre eigene Zuordnung zu schreiben - eher als vollständig dynamisch zu sein. Es gibt jedoch einige "Klon"-Tricks, die Sie verwenden können, um verschiedene Effekte zu erzielen.
Ich werde den folgenden Code für alle nachfolgenden Beispiele verwenden:
class Example {
constructor(public type: string) {
}
}
class Customer {
constructor(public name: string, public example: Example) {
}
greet() {
return 'Hallo ' + this.name;
}
}
var customer = new Customer('David', new Example('DavidType'));
Option 1: Spread
Eigenschaften: Ja
Methoden: Nein
Tiefenkopie: Nein
var clone = { ...customer };
alert(clone.name + ' ' + clone.example.type); // David DavidType
//alert(clone.greet()); // Nicht OK
clone.name = 'Steve';
clone.example.type = 'SteveType';
alert(customer.name + ' ' + customer.example.type); // David SteveType
Option 2: Object.assign
Eigenschaften: Ja
Methoden: Nein
Tiefenkopie: Nein
var clone = Object.assign({}, customer);
alert(clone.name + ' ' + clone.example.type); // David DavidType
alert(clone.greet()); // Nicht OK, obwohl der Compiler es nicht bemerken wird
clone.name = 'Steve';
clone.example.type = 'SteveType';
alert(customer.name + ' ' + customer.example.type); // David SteveType
Option 3: Object.create
Eigenschaften: Vererbt
Methoden: Vererbt
Tiefenkopie: Flach vererbt (tiefe Änderungen betreffen sowohl das Original als auch den Klon)
var clone = Object.create(customer);
alert(clone.name + ' ' + clone.example.type); // David DavidType
alert(clone.greet()); // OK
customer.name = 'Misha';
customer.example = new Example("MishaType");
// Der Klon sieht Änderungen am Original
alert(clone.name + ' ' + clone.example.type); // Misha MishaType
clone.name = 'Steve';
clone.example.type = 'SteveType';
// Das Original sieht Änderungen am Klon
alert(customer.name + ' ' + customer.example.type); // Misha SteveType
Option 4: Deep Copy Function
Eigenschaften: Ja
Methoden: Nein
Tiefenkopie: Ja
function deepCopy(obj) {
var copy;
// Behandle die 3 einfachen Typen, sowie null oder undefined
if (null == obj || "object" != typeof obj) return obj;
// Behandle Datum
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Behandle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = deepCopy(obj[i]);
}
return copy;
}
// Behandle Objekt
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = deepCopy(obj[attr]);
}
return copy;
}
throw new Error("Kann das Objekt nicht kopieren! Der Typ wird nicht unterstützt.");
}
var clone = deepCopy(customer) as Customer;
alert(clone.name + ' ' + clone.example.type); // David DavidType
// alert(clone.greet()); // Nicht OK - nicht wirklich ein Kunde
clone.name = 'Steve';
clone.example.type = 'SteveType';
alert(customer.name + ' ' + customer.example.type); // David DavidType