[解決済み】タイプスクリプト - オブジェクトのクローンを作成する
質問
親となるスーパークラスがあるのですが(
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.
スクリプトは動作するものの トランスパイルエラーをなくしたいです。
解決方法を教えてください。
具体的な問題解決
タイプアサーションを使用することで、コンパイラに自分の知識があることを伝えることができます。
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;
}
クローン作成
時には、完全にダイナミックにマッピングするよりも、独自のマッピングを書いた方が良い場合があることを心に留めておいてください。しかし、いくつかの「クローン」トリックを使用することで、異なる効果を得ることができます。
この後の例では、すべて次のコードを使用します。
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
関連
-
[解決済み】このエラーの原因は何ですか - "Fatal error: ローカルgruntを見つけることができません"
-
[解決済み】ETIMEDOUTエラーの対処方法は?
-
[解決済み】 \u003C とは何ですか?
-
[解決済み] JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?
-
[解決済み] JavaScriptのオブジェクトが空であることをテストするにはどうすればよいですか?
-
[解決済み] JavaScriptのオブジェクトにキーが存在するかどうかをチェックする?
-
[解決済み] JavaScriptのオブジェクトをループスルーまたは列挙するにはどうすればよいですか?
-
[解決済み】未定義のオブジェクトプロパティを検出する
-
[解決済み】JavaScriptのオブジェクトの長さ
-
[解決済み】TypeScriptのインターフェースと型について
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】TypeError: 'undefined'はオブジェクトではありません。
-
[解決済み】Uncaught ReferenceError: angular is not defined - AngularJSが動作しない。
-
[解決済み】最大呼び出しスタックサイズ超過エラーとその修正方法とは?
-
[解決済み】Google Conversionsが動作しない - スクリプトが読み込まれない
-
[解決済み】ある要素が可視DOMに存在するかどうかを確認するにはどうすればいいですか?
-
[解決済み] テスト
-
[解決済み】WebSocket接続に失敗しました。WebSocket のハンドシェイク中にエラーが発生しました。予期しない応答コードです。400
-
[解決済み】 \u003C とは何ですか?
-
[解決済み] [Solved] Uncaught Invariant Violation: 前のレンダリング中よりも多くのフックをレンダリングする
-
[解決済み] JavaScriptでオブジェクトをディープクローンする最も効率的な方法は何ですか?