2015-12-10 10 views
7

TypeScriptでオブジェクトを詳細に複製する必要があります。 Lodashのようなライブラリが適切な機能を提供するので、これは問題ではありません。しかし、これらは型情報を破棄するように見えます。TypeScriptの深いクローン(保存タイプ)

> var a = new SomeClass(); 
> a instanceof SomeClass; 
< true 
> var b = _.cloneDeep(a); 
> b instanceof SomeClass; 
< false 

このタイピング情報を保持しながらTypeScriptでオブジェクトをクローンする方法はありますか?

+0

'b:typeof a'のようなものですか? – YOU

+4

自動的に?いいえ。オブジェクトとそのネストされたオブジェクトにクローンメソッドを実装する必要があります。 –

+0

Typescriptの型を保持し、SomeClass.prototypeを保持することは同じではありません。 @Retsam answerとhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceofを参照してください。 typescriptの型は実行時に消去されます。 –

答えて

6

活字体は、ここに型情報を破棄されていません:あなたは深いクローニングclone()機能の作者の実装を使用することができます。 DefinitelyTyped lodash.d.tsファイルでは、あなたがcloneDeepが、我々は気にしない引数を無視

cloneDeep<T>(
    val: T, 
    customizer?: (value: any) => any, 
    thisArg?: any 
) : T 

として定義されていることを見ることができ、それは、入力としてTを受け取り、出力としてTを出してくれる。したがって、Typescriptは型情報を失うことはありません。 cloneDeepの出力を入力と同じタイプと見なします。

これは、変数のタイプやオートコンプリートメソッドを調べるためのエディタを持っていることを前提としています(エディタを使用しないと強く推奨します)。


なぜ、typeofが期待どおりに機能しないのですか?これは、Typescript型の情報が実行時に継承されないためです。

"use strict"; 
 
class A {} 
 

 
let a = new A(); 
 
let b = _.cloneDeep(a); 
 

 
if (b instanceof A) { 
 
    alert("b is an instance of A"); 
 
} else { 
 
    alert("b is not an instance of A"); 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>

b instanceof Aがfalseであることを理由にinstanceofがチェックされていることである:instanceofは活字体は、このスニペットを実行することにより、あなたが見ることができる、の動作を変更しないネイティブJS演算子であり、 x instanceof Aは、関数Aがxのプロトタイプチェーンのどこかのコンストラクタである場合にtrueを返します(instanceofのMDNドキュメントを参照)。しかし、Lodashはオブジェクトをクローンするときにコンストラクタを使用しません。それはできません。 (どのような引数を渡すべきでしょうか?)クローンオブジェクトのすべてのメソッドを持ち、プロトタイプチェーンを再現しないプレーンなJSオブジェクトを作成します。

Lodashのclone(およびlodashのメソッドのほとんどは、実際に)生のJSオブジェクトを扱うときに最もよく使用されています。あなたがコンストラクタと一緒にそれを使用している場合は、instanceofチェック作業は少しばかりです。ここ


一つの解決策は、instanceofチェックを回避し、ダックタイピングに似何かを行うことです。オブジェクトのコンストラクタが特定の関数であるかどうかをチェックしないでください。ただし、オブジェクトに期待するプロパティがあることを確認してください。

コメントの中に示唆されているように、別の解決方法は、クラス自体にクローンメソッドを実装することです。これはlodashを使用しません。

class A() { 
    clone() { 
     var cloned = new A(); //pass appropriate constructor args 
     //make other necessary changes to make the state match 
     return cloned; 
    } 
} 
1

Lodash#cloneDeepユーティリティを使用できます。使用例:

import * as _ from "lodash"; 

... 

{ 
    this.cloned = _.cloneDeep(data); 
} 
関連する問題