Entity
多くのサブクラス ( Customer
、Product
、ProductCategory
...)の親 ( ) となるスーパークラスがあります。
Typescript で異なるサブオブジェクトを含むオブジェクトを動的に複製したいと考えています。
例:Customer
異なるをProduct
持つProductCategory
var cust:Customer = new Customer ();
cust.name = "someName";
cust.products.push(new Product(someId1));
cust.products.push(new Product(someId2));
オブジェクトのツリー全体を複製するために、関数を作成しました。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;
}
new
これを JavaScript にトランスパイルすると、次のエラーが発生します。error TS2351: Cannot use 'new' with an expression whose type lacks a call or construct signature.
スクリプトは動作しますが、トランスパイルされたエラーを取り除きたいです
ベストアンサー1
特定の問題を解決する
型アサーションを使用すると、コンパイラーに自分がよりよく知っていることを伝えることができます。
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;
}
クローン
2022年現在、structuredClone
多くの型をディープコピーできるようにする提案があります。
const copy = structuredClone(value)
いくつかの制限がありますこれは何に使えるのか。
完全に動的にするよりも、独自のマッピングを記述する方がよい場合もあります。ただし、さまざまな効果をもたらす「クローン」トリックがいくつかあります。
以降のすべての例では次のコードを使用します。
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'));
オプション1: スプレッド
プロパティ:はい
メソッド: いいえ
ディープコピー: いいえ
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
オプション2: Object.assign
プロパティ:はい
メソッド: いいえ
ディープコピー: いいえ
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
オプション3: Object.create
プロパティ:継承
メソッド:継承
ディープ コピー:浅い継承(ディープ変更はオリジナルとクローンの両方に影響します)
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
オプション4: ディープコピー機能
プロパティ:はい
メソッド: いいえ
ディープコピー:はい
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