2017-11-09 6 views
0

私は配列のオブジェクトを別のものに置き換えるメソッドを持っています。 IDで検索し、指定されたIDで一致するすべてのレコードを変更します。typescriptのパラメータとしてオブジェクトパスを渡す

私が渡し任意のオブジェクトタイプに対して同じように動作することができ、一般的な、再利用可能な方法に変更したいと思います(EG:car.idcar.door.idcar.trunkMonkey.id、など)。

があります私がこのメソッドに変数として "element.car.id"パスを渡す方法はありますか?

updateArrayObject(item: any, data: any[]) { 
     // Parse all objects in the array, looking for matches by ID 
     data.forEach(element => { 
      if (element.car.id === item.id) { // <-- Can I pass "element.car.id" into the method somehow? 
       // Item ID matches. Replace the item. 
       element.car = item; 
      } 
     }); 
    } 
+0

これはあなたを助けるかもしれない: https://stackoverflow.com/questions/8817394/javascript-get-deep-をパスからオブジェクトへのパスから値への文字列として – Easy

答えて

2

プログラムによっては、これをストリング("element.car.id")で実行し、実行時にパスを解析します。残念ながらタイプセーフではありません。ここ

これはもう少し複雑であり、その限界を持っていますが、それはタイプセーフです:

function updateArrayObject<T, R>(// ElementType, ReplacementType 
    data: T[], // The array 
    getter: (element: T) => R, // Getter of the thing that might be replaced 
    setter: (element: T, replacement: R) => void, // Setter of the replacement, when appropriate 
    keyComparer: (candidate: R, replacement: R) => boolean, // The matching predicate 
    replacement: R) { // The replacement 

    data.forEach(element => { 
     if (keyComparer(getter(element), replacement)) { 
      setter(element, replacement); 
     } 
    }); 
} 

var sample: Element[] = [ /* ... */ ]; 

// Your car example 
updateArrayObject<Element, Car>(
    sample, 
    e => e.car, 
    (e, r) => { e.car = r }, 
    (left, right) => left.id === right.id, 
    { 
     id: 42, 
     door: { id: 0, name: 'driver' }, 
     trunkMonkey: { id: 0, tmName: 'bozo' } 
    }) 

// Your trunkMonkey example 
updateArrayObject<Element, TrunkMonkey>(
    sample, 
    e => e.car.trunkMonkey, 
    (e, r) => { e.car.trunkMonkey = r }, 
    (left, right) => left.id === right.id, 
    { 
     id: 0, tmName: 'bozo' 
    }) 

// The various custom types involved. 
interface Door { id: number, name: string } 
interface TrunkMonkey { id : number, tmName: string } 
interface Car { 
    id: number, 
    door: Door, 
    trunkMonkey: TrunkMonkey 
} 
interface Element { 
    car: Car, 
    otherElementData: any 
} 

あなたはまた、「機能のレンズを」研究かもしれません。ここ

+1

あなたは正しいでしょう。これは、私が望んでいたよりも複雑でしたが、私のすべてのニーズに対してうまく働いているようです。 Bozoトランクモンキーありがとう! – Rethic

0

は... ciblecarまたはdoorすることができ、あなたの一般的な機能である:

updateArrayObject(item: any, data: any[], cible) { 
     // Parse all objects in the array, looking for matches by ID 
     data.forEach(element => { 
      if (element[cible].id === item.id) { // <-- Can I pass "element.car.id" into the method somehow? 
       // Item ID matches. Replace the item. 
       element[cible]= item; 
      } 
     }); 
    } 
+0

"要素がデータ配列の兄弟のクローンであるため、配列は更新されません" 'forEach()'はクローン化せず、要素を置き換えていないので、要素上のメンバの値を置き換えています。 –

+0

あなたは正しいです、私は更新しています –

+0

これは私がやろうとしていたようですが、それを呼び出す方法を理解するのが難しいです。あなたは "cible"変数として何を渡しますか? – Rethic

関連する問題