Typoskript - Klonen von Objekten

183

Ich habe eine Superklasse , die die Eltern (ist Entity) für viele Unterklasse ( Customer, Product, ProductCategory...)

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

Im Beispiel: a Customerdas hat anders Productwer hat aProductCategory

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 erstellt Entity

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 newfolgende Fehler tritt auf, wenn er in Javascript transpiliert wird:error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.

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

David Laberge
quelle

Antworten:

251

Lösen des spezifischen Problems

Sie können eine Typzusicherung verwenden, um dem Compiler mitzuteilen, 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

Denken Sie daran, dass es manchmal besser ist, ein eigenes Mapping zu schreiben, als völlig dynamisch zu sein. Es gibt jedoch einige "Klon" -Tricks, mit denen Sie unterschiedliche Effekte erzielen können.

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 'Hello ' + this.name;
  }
}

var customer = new Customer('David', new Example('DavidType'));

Option 1: Ausbreiten

Eigenschaften: Ja
Methoden: Nein
Deep Copy: Nein

var clone = { ...customer };

alert(clone.name + ' ' + clone.example.type); // David DavidType
//alert(clone.greet()); // Not OK

clone.name = 'Steve';
clone.example.type = 'SteveType';

alert(customer.name + ' ' + customer.example.type); // David SteveType

Option 2: Object.assign

Eigenschaften: Ja
Methoden: Nein
Deep Copy: Nein

var clone = Object.assign({}, customer);

alert(clone.name + ' ' + clone.example.type); // David DavidType
alert(clone.greet()); // Not OK, although compiler won't spot it

clone.name = 'Steve';
clone.example.type = 'SteveType';

alert(customer.name + ' ' + customer.example.type); // David SteveType

Option 3: Object.create

Eigenschaften: Vererbt
Methoden: Vererbt
Tiefe Kopie: Flach Vererbt (tiefe Änderungen wirken sich sowohl auf das Original als auch auf den Klon aus)

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

// clone sees changes to original 
alert(clone.name + ' ' + clone.example.type); // Misha MishaType

clone.name = 'Steve';
clone.example.type = 'SteveType';

// original sees changes to clone
alert(customer.name + ' ' + customer.example.type); // Misha SteveType

Option 4: Deep Copy-Funktion

Eigenschaften: Ja
Methoden: Nein
Deep Copy: Ja

function deepCopy(obj) {
    var copy;

    // Handle the 3 simple types, and null or undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = deepCopy(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = deepCopy(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}

var clone = deepCopy(customer) as Customer;

alert(clone.name + ' ' + clone.example.type); // David DavidType
// alert(clone.greet()); // Not OK - not really a customer

clone.name = 'Steve';
clone.example.type = 'SteveType';

alert(customer.name + ' ' + customer.example.type); // David DavidType
Fenton
quelle
Schließen, das Transpile hat aufgehört, sich mit Typoskript 1.3 zu beschweren, aber sobald es in Javascript ist, würde es einen Fehler auslösen. Typoskript 1.4.1 lässt es nicht los.
David Laberge
Sie können Generika verwenden, um ein Ergebnis des gleichen Typs zurückzugewinnen, den Sie klonen.
Robmcm
1
Wären Sie in der Lage zu klären, wie Sie dies genau verwenden? Ich habe als Methode mein Objekt aufgenommen und dann eine Fehlermeldung erhalten, dass es keine Funktion ist ...
Megalucio
1
Ich erhalte die folgende Fehlermeldung: "ERROR TypeError: this.constructor (...) ist kein Konstruktor"
michali
3
Haben Sie aus diesem Kunden gerade ein öffentliches Beispiel gemacht?
Blair Connolly
174

1.Verwenden Sie den Spread-Operator

const obj1 = { param: "value" };
const obj2 = { ...obj1 };

Der Spread-Operator nimmt alle Felder aus obj1 und verteilt sie über obj2. Im Ergebnis erhalten Sie ein neues Objekt mit einer neuen Referenz und denselben Feldern wie das ursprüngliche.

Denken Sie daran, dass es sich um eine flache Kopie handelt. Wenn ein Objekt verschachtelt ist, sind seine verschachtelten zusammengesetzten Parameter im neuen Objekt mit derselben Referenz vorhanden.

2.Object.assign ()

const obj1={ param: "value" };
const obj2:any = Object.assign({}, obj1);

Object.assign erstellt eine echte Kopie, jedoch nur eigene Eigenschaften, sodass Eigenschaften im Prototyp im kopierten Objekt nicht vorhanden sind. Es ist auch eine flache Kopie.


3.Object.create ()

const obj1={ param: "value" };
const obj2:any = Object.create(obj1);

Object.create führt kein echtes Klonen durch , sondern erstellt ein Objekt aus einem Prototyp. Verwenden Sie es daher, wenn das Objekt Eigenschaften des Primärtyps klonen soll, da die Zuweisung der Eigenschaften des Primärtyps nicht als Referenz erfolgt.

Pluspunkte von Object.create sind, dass alle im Prototyp deklarierten Funktionen in unserem neu erstellten Objekt verfügbar sind.


Einige Dinge über flache Kopien

Bei einer flachen Kopie werden alle Felder des alten in ein neues Objekt eingefügt. Wenn das ursprüngliche Objekt jedoch zusammengesetzte Felder (Objekt, Arrays usw.) enthält, werden diese Felder in ein neues Objekt mit denselben Referenzen eingefügt. Die Mutation eines solchen Feldes im ursprünglichen Objekt wird in einem neuen Objekt wiedergegeben.

Es sieht vielleicht wie eine Falle aus, aber eine Situation, in der das gesamte komplexe Objekt kopiert werden muss, ist selten. Flache Kopien verwenden den größten Teil des Speichers wieder, was bedeutet, dass dies im Vergleich zu tiefen Kopien sehr billig ist.


Tiefe Kopie

Der Spread-Operator kann für tiefe Kopien nützlich sein.

const obj1 = { param: "value", complex: { name: "John"}}
const obj2 = { ...obj1, complex: {...obj1.complex}};

Über dem Code wurde eine tiefe Kopie von obj1 erstellt. Das zusammengesetzte Feld "Komplex" wurde ebenfalls in obj2 kopiert. Das Mutationsfeld "komplex" spiegelt die Kopie nicht wider.

Maciej Sikora
quelle
8
Ich denke nicht, dass das völlig richtig ist. Object.create(obj1)erstellt ein neues Objekt und weist obj1 als Prototyp zu. Keines der Felder in obj1 wird kopiert oder geklont. Änderungen an obj1 ohne Änderung von obj2 werden also angezeigt, da es im Wesentlichen keine Eigenschaften hat. Wenn Sie zuerst obj2 ändern, wird der Prototyp für das von Ihnen definierte Feld nicht angezeigt, da das Feld von obj2 mit dem Namen näher in der Hierarchie liegt.
Ken Rimple
3
Sie werden stattdessen auch ES2015- und Typoskript-Entwickler sehen, die ein Objekt aus dem 1. Parameter (in meinem Fall ein leeres) erstellen und die Eigenschaften aus dem zweiten und den folgenden Parametern kopieren: let b = Object.assign({}, a);
Ken Rimple
@ KenRimple Sie haben zu 100% Recht, ich habe einige weitere Informationen hinzugefügt.
Maciej Sikora
vielleicht hilfreich sein => developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Emmanuel Touzery
5
Object.assign erstellt Probleme für tiefe Objekte. Zum Beispiel {Name: 'x', Werte: ['a', 'b', 'c']}. Nachdem Sie Object.assign zum Klonen verwendet haben, teilen sich beide Objekte das Werte-Array, sodass sich die Aktualisierung auf das andere auswirkt. Siehe: developer.mozilla.org/en/docs/Web/JavaScript/Reference/… (Abschnitt "Warnung für Deep Clone"). Es heißt: Für das tiefe Klonen müssen wir andere Alternativen verwenden. Dies liegt daran, dass Object.assign () die Eigenschaftsreferenz kopiert, wenn die zugewiesene Eigenschaft ein Objekt ist.
Meir
45

Versuche dies:

let copy = (JSON.parse(JSON.stringify(objectToCopy)));

Dies ist eine gute Lösung, bis Sie sehr große Objekte verwenden oder Ihr Objekt unserialisierbare Eigenschaften hat.

Um die Typensicherheit zu gewährleisten, können Sie eine Kopierfunktion in der Klasse verwenden, von der Sie Kopien erstellen möchten:

getCopy(): YourClassName{
    return (JSON.parse(JSON.stringify(this)));
}

oder statisch:

static createCopy(objectToCopy: YourClassName): YourClassName{
    return (JSON.parse(JSON.stringify(objectToCopy)));
}
Lars
quelle
5
Dies ist in Ordnung, aber Sie sollten bedenken, dass Sie beim Serialisieren / Parsen Prototypinformationen und alle in json nicht unterstützten Typen verlieren.
Stanislav E. Govorov
1
Auch scheint dies weniger effizient auf die Funktion zur Verfügung gestellt Vergleich deepcopy oben .
Mojtaba
Ich habe diesen Fehler: "Konvertieren einer Kreisstruktur in JSON", wenn ich "(JSON.parse (JSON.stringify (objectToCopy)))" verwende;
Cedric Arnould
Funktioniert nur in 98% der Fälle. Kann undefinedzumindest zu fehlenden Schlüsseln mit Wert führen. Wenn objectToCopy = { x : undefined};dann nach dem Ausführen Ihr Code Object.keys(objectToCopy).lengthist 1, während Object.keys(copy).lengthist 0.
Aidin
31

TypeScript / JavaScript hat einen eigenen Operator für das flache Klonen:

let shallowClone = { ...original };
Luca C.
quelle
15

Mit "Object Spread", das in TypeScript 2.1 eingeführt wurde, ist es einfach, eine flache Kopie zu erhalten

dieses TypeScript: let copy = { ...original };

erzeugt dieses JavaScript:

var __assign = (this && this.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
var copy = __assign({}, original);

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

Homer
quelle
2
Hinweis: Dadurch wird eine flache Kopie erstellt
Jimmy Kane
11

Für serialisierbare tiefe Klone mit Typinformationen gilt:

export function clone<T>(a: T): T {
  return JSON.parse(JSON.stringify(a));
}
Polv
quelle
Dies kann die Reihenfolge der Requisiten ändern. Nur eine Warnung für einige Leute. Außerdem werden Daten nicht richtig behandelt.
Pangamma
Dies kann die Reihenfolge der Requisiten ändern - versuchen Sie vielleicht npmjs.com/package/es6-json-stable-stringify anstelle vonJSON.stringify
Polv
@Polv, wenn sich jemand auf die Reihenfolge der Schlüssel in einem Objekt verlässt, denke ich, dass er ein größeres Problem hat als clone. :)
Aidin
Diese Lösung kann Schlüssel mit undefinedWert verfehlen . Siehe meinen Kommentar zu der ähnlichen Antwort oben: stackoverflow.com/questions/28150967/typescript-cloning-object/…
Aidin
7

Meine Meinung dazu:

Object.assign(...) kopiert nur Eigenschaften und wir verlieren den Prototyp und die Methoden.

Object.create(...) kopiert für mich keine Eigenschaften und erstellt nur einen Prototyp.

Für mich hat es funktioniert, einen Prototyp zu erstellen Object.create(...)und Eigenschaften zu kopieren, indem ich Object.assign(...):

Erstellen Sie für ein Objekt fooeinen Klon wie folgt:

Object.assign(Object.create(foo), foo)
Muhammad Ali
quelle
Hier ist eine sehr subtile Sache vor sich. Sie machen tatsächlich foodas prototypische Elternteil des clonedFoo(neuen Objekts). Dies mag zwar in Ordnung klingen, Sie sollten jedoch berücksichtigen, dass eine fehlende Eigenschaft in der Prototypenkette nachgeschlagen wird. const a = { x: 8 }; const c = Object.assign(Object.create(a), a); delete c.x; console.log(c.x);Drucken Sie also 8 aus, solange dies der Fall sein sollte undefined! (REPL-Link: repl.it/repls/CompetitivePreemptiveKeygen )
Aidin
Wenn Sie später eine Eigenschaft hinzufügen foo, wird diese automatisch für clonedFooangezeigt! zB foo.y = 9; console.log(clonedFoo.y)wird auszudrucken 9von statt undefined. Es ist sehr wahrscheinlich, dass es nicht das ist, wonach Sie fragen!
Aidin
5

Sie können auch so etwas haben:

class Entity {
    id: number;

    constructor(id: number) {
        this.id = id;
    }

    clone(): this {
        return new (this.constructor as typeof Entity)(this.id) as this;
    }
}

class Customer extends Entity {
    name: string;

    constructor(id: number, name: string) {
        super(id);
        this.name = name;
    }

    clone(): this {
        return new (this.constructor as typeof Customer)(this.id, this.name) as this;
    }
}

Stellen Sie einfach sicher, dass Sie die cloneMethode in allen EntityUnterklassen überschreiben, da Sie sonst teilweise Klone erhalten.

Der Rückgabetyp von entspricht thisimmer dem Typ der Instanz.

Jahrzehntelanger Mond
quelle
3

Wenn Sie diesen Fehler erhalten:

TypeError: this.constructor(...) is not a function

Dies ist das richtige Skript:

public clone(): any {
    var cloneObj = new (<any>this.constructor)(); // line fixed
    for (var attribut in this) {
        if (typeof this[attribut] === "object") {
            cloneObj[attribut] = this[attribut].clone();
        } else {
            cloneObj[attribut] = this[attribut];
        }
    }
    return cloneObj;
}
pablorsk
quelle
4
Ist richtig cloneObj[attribut] = this.clone();? oder du meinstcloneObj[attribut] = this[attribut].clone();
Serginho
2

Ich bin auf dieses Problem selbst gestoßen und habe am Ende eine kleine Bibliothek geschrieben, die klonbar ist und eine abstrakte Klasse bereitstellt, die jeder Klasse, die sie erweitert, eine Klonmethode hinzufügt. Die abstrakte Klasse leiht ich die Deep Copy - Funktion in der akzeptierten Antwort beschrieben durch Fenton nur ersetzt copy = {};mit copy = Object.create(originalObj)der Klasse des ursprünglichen Objekts zu erhalten. Hier ist ein Beispiel für die Verwendung der Klasse.

import {Cloneable, CloneableArgs} from 'cloneable-ts';

// Interface that will be used as named arguments to initialize and clone an object
interface PersonArgs {
    readonly name: string;
    readonly age: number;
}

// Cloneable abstract class initializes the object with super method and adds the clone method
// CloneableArgs interface ensures that all properties defined in the argument interface are defined in class
class Person extends Cloneable<TestArgs>  implements CloneableArgs<PersonArgs> {
    readonly name: string;
    readonly age: number;

    constructor(args: TestArgs) {
        super(args);
    }
}

const a = new Person({name: 'Alice', age: 28});
const b = a.clone({name: 'Bob'})
a.name // Alice
b.name // Bob
b.age // 28

Oder Sie können einfach die Cloneable.cloneHilfsmethode verwenden:

import {Cloneable} from 'cloneable-ts';

interface Person {
    readonly name: string;
    readonly age: number;
}

const a: Person = {name: 'Alice', age: 28};
const b = Cloneable.clone(a, {name: 'Bob'})
a.name // Alice
b.name // Bob
b.age // 28    
Tim Osadchiy
quelle
2

Hier ist mein Mash-up! Und hier ist ein StackBlitz-Link dazu. Es beschränkt sich derzeit nur auf das Kopieren einfacher Typen und Objekttypen, könnte aber meiner Meinung nach leicht geändert werden.

   let deepClone = <T>(source: T): { [k: string]: any } => {
      let results: { [k: string]: any } = {};
      for (let P in source) {
        if (typeof source[P] === 'object') {
          results[P] = deepClone(source[P]);
        } else {
          results[P] = source[P];
        }
      }
      return results;
    };
marckassay
quelle
1
Funktioniert ziemlich gut, soweit ich sehen kann. Ist typeof nulljedoch auch ein Objekt, sollte die Abfrage if (source[P] !== null && typeof source[P] === 'object')stattdessen sein. Andernfalls werden Ihre Nullwerte in ein leeres Objekt umgewandelt.
MortenMoulder
2

Fügen Sie "lodash.clonedeep": "^4.5.0"Ihrem hinzu package.json. Dann verwenden Sie wie folgt:

import * as _ from 'lodash';

...

const copy = _.cloneDeep(original)
user2878850
quelle
1

Seit der Veröffentlichung von TypeScript 3.7 werden jetzt rekursive Typaliasnamen unterstützt, mit denen wir eine typsichere deepCopy()Funktion definieren können:

// DeepCopy type can be easily extended by other types,
// like Set & Map if the implementation supports them.
type DeepCopy<T> =
    T extends undefined | null | boolean | string | number ? T :
    T extends Function | Set<any> | Map<any, any> ? unknown :
    T extends ReadonlyArray<infer U> ? Array<DeepCopy<U>> :
    { [K in keyof T]: DeepCopy<T[K]> };

function deepCopy<T>(obj: T): DeepCopy<T> {
    // implementation doesn't matter, just use the simplest
    return JSON.parse(JSON.stringify(obj));
}

interface User {
    name: string,
    achievements: readonly string[],
    extras?: {
        city: string;
    }
}

type UncopiableUser = User & {
    delete: () => void
};

declare const user: User;
const userCopy: User = deepCopy(user); // no errors

declare const uncopiableUser: UncopiableUser;
const uncopiableUserCopy: UncopiableUser = deepCopy(uncopiableUser); // compile time error

Spielplatz

Valeriy Katkov
quelle
0

Für einen einfachen Klon des Inhalts des Hole-Objekts werde ich die Instanz einfach stringifizieren und analysieren:

let cloneObject = JSON.parse(JSON.stringify(objectToClone))

Während ich Daten im objectToClone-Baum ändere, gibt es in cloneObject keine Änderung. Das war meine Anforderung.

Hoffe es hilft

Ferhatos
quelle
1
Kann Schlüssel mit undefinedWert verfehlen . Siehe meinen Kommentar zu der ähnlichen Antwort oben: stackoverflow.com/questions/28150967/typescript-cloning-object/…
Aidin
0

Am Ende tat ich:

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

  // some deserialization code I hade in place already...
  // which deep copies all serialized properties of the
  // object graph
  // result.deserialize(this)

  // you could use any of the usggestions in the other answers to
  // copy over all the desired fields / properties

  return result;
}

Weil:

var cloneObj = new (<any>this.constructor());

von @Fenton gab Laufzeitfehler.

Typoskript-Version: 2.4.2

Bernoulli IT
quelle
0

Wie wäre es mit guter alter jQuery?! Hier ist ein tiefer Klon:

var clone = $.extend(true, {}, sourceObject);
Alehro
quelle
Diese Frage wurde weder mit JQuery markiert, noch wurde JQuery in der Frage erwähnt. Es wäre auch ein enormer Aufwand, JQuery in ein Projekt einzubeziehen, nur um einen tiefen Klon zu erstellen.
LewisM
Das ist fair genug, aber beim OP geht es nicht darum, wie geklont werden soll, sondern darum, ein Problem in dem von ihm bereitgestellten Code zu identifizieren, und Sie haben mit der jQuery-Methode zum Klonen geantwortet, ohne die Frage wirklich zu beantworten. Ich bin nicht derjenige, der dich herabgestimmt hat, aber ich glaube, das könnte der Grund sein, warum du herabgestimmt wurdest.
LewisM
0

Ich habe versucht, einen generischen Kopier- / Klondienst zu erstellen, der Typen für verschachtelte Objekte beibehält. Würde mich über Feedback freuen, wenn ich etwas falsch mache, aber es scheint soweit zu funktionieren ...

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

@Injectable()
export class CopyService {

  public deepCopy<T>(objectToClone: T): T {
    // If it's a simple type or null, just return it.
    if (typeof objectToClone === 'string' ||
      typeof objectToClone === 'number' ||
      typeof objectToClone === 'undefined' ||
      typeof objectToClone === 'symbol' ||
      typeof objectToClone === 'function' ||
      typeof objectToClone === 'boolean' ||
      objectToClone === null
    ) {
      return objectToClone;
    }

    // Otherwise, check if it has a constructor we can use to properly instantiate it...
    let ctor = Object.getPrototypeOf(objectToClone).constructor;
    if (ctor) {
      let clone = new ctor();

      // Once we've instantiated the correct type, assign the child properties with deep copies of the values
      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('object cloned, but doesnt match exactly...\nobject: ' + JSON.stringify(objectToClone) + "\nclone: " + JSON.stringify(clone))

      // return our cloned object...
      return clone;
    }
    else {
      //not sure this will ever get hit, but figured I'd have a catch call.
      console.log('deep copy found something it didnt know: ' + JSON.stringify(objectToClone));
      return objectToClone;
    }
  }
}
Patrickbadley
quelle
0

In TypeScript teste ich mit Angular und es geht OK

deepCopy(obj) {


        var copy;

        // Handle the 3 simple types, and null or undefined
        if (null == obj || "object" != typeof obj) return obj;

        // Handle Date
        if (obj instanceof Date) {
            copy = new Date();
            copy.setTime(obj.getTime());
            return copy;
        }

        // Handle Array
        if (obj instanceof Array) {
            copy = [];
            for (var i = 0, len = obj.length; i < len; i++) {
                copy[i] = this.deepCopy(obj[i]);
            }
            return copy;
        }

        // Handle Object
        if (obj instanceof Object) {
            copy = {};
            for (var attr in obj) {
                if (obj.hasOwnProperty(attr)) copy[attr] = this.deepCopy(obj[attr]);
            }
            return copy;
        }

        throw new Error("Unable to copy obj! Its type isn't supported.");
    }
maty jimenez
quelle
0

Zum tiefen Klonen eines Objekts, das andere Objekte, Arrays usw. enthalten kann, verwende ich:

const clone = <T>(source: T): T => {
  if (source === null) return source

  if (source instanceof Date) return new Date(source.getTime()) as any

  if (source instanceof Array) return source.map((item: any) => clone<any>(item)) as any

  if (typeof source === 'object' && source !== {}) {
    const clonnedObj = { ...(source as { [key: string]: any }) } as { [key: string]: any }
    Object.keys(clonnedObj).forEach(prop => {
      clonnedObj[prop] = clone<any>(clonnedObj[prop])
    })

    return clonnedObj as T
  }

  return source
}

Verwenden:

const obj = {a: [1,2], b: 's', c: () => { return 'h'; }, d: null, e: {a:['x'] }}
const objClone = clone(obj)
RTW
quelle
0

Sie können die Destrukturierungszuweisung mit Spread-Syntax verwenden :

var obj = {id = 1, name = 'product1'};
var clonedObject = {...obj};
SOUVIK SAHA
quelle
1
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Leopal
-2

Wenn Sie das Zielobjekt bereits haben und es nicht neu erstellen möchten (z. B. beim Aktualisieren eines Arrays), müssen Sie die Eigenschaften kopieren.
Wenn Sie es so gemacht haben:

Object.keys(source).forEach((key) => {
    copy[key] = source[key]
})

Lob gebührt. (siehe Überschrift "Version 2")

LosManos
quelle
Funktionen? Arrays? Datumsobjekte? Artenerhaltung? Und natürlich was ist mit Objekten? Wenn die obige Funktion auf einen der oben genannten Typen stößt, kann sie nicht tief geklont werden. Sie haben die Verweise auf dieselben Daten kopiert. Wenn sie die untergeordneten Eigenschaften des geklonten Objekts bearbeiten, wird am Ende auch das ursprüngliche Objekt bearbeitet.
Pangamma