2016-08-12 17 views
3

インデックスプロパティをtypescriptのメンバーに委任する方法はありますか?私はラッパーを書いています、そして、私はラッピングしているオブジェクトにインデックスプロパティを委託したいと思います。typescriptのindexプロパティを委譲する方法はありますか?

のようなもの:それはこのような構築のためのJavaScriptコードを生成することはできませんので、活字体はこのために許可されていません

interface MyStringArray { 
    length : number; 
    clear() : void; 
    [index: number] : string; 
} 

export class MyStringArrayWrapper implements MyStringArray { 

    private wrapped : MyStringArray; 

    public get length() : number { 
     return this.wrapped.length; 
    } 

    public clear() : void { 
     this.wrapped.clear(); 
    } 

    // This doesn't work 
    public get [index : number] : string { 
     return this.wrapped[index]; 
    } 

    // This doesn't work either 
    public set [index : number](value: string) { 
     this.wrapped[index] = value; 
    } 
} 

答えて

2

を。 のいずれかのプロパティが設定されているときに呼び出されるクラスに対してキャッチオールゲッター/セッターを定義する方法はJavaScriptにありません。

私が得ることができる最も近いクラスにhasItemgetItemsetItemメソッドを定義し、その後のすべてのインスタンスをラップすることにより、すべてのget sおよびset秒をプロキシES2015 Proxyオブジェクトでそのクラスのプロトタイプそのインスタンスのプロパティ

function isArrayIndex(key) { 
 
    var keyAsNumber = +key; // convert string to number 
 
    if (keyAsNumber < 0) { 
 
     return false; // must be positive or zero 
 
    } 
 
    if (keyAsNumber !== keyAsNumber|0) { 
 
     return false; // must be integer 
 
    } 
 
    return true; 
 
} 
 

 
function toArrayIndex(key) { 
 
    return key|0; // convert string to integer 
 
} 
 

 
function MyArrayWrapper(wrapped) { 
 
    this.wrapped = wrapped; 
 
} 
 
    
 
MyArrayWrapper.prototype = { 
 
    get length() { 
 
     return this.wrapped.length; 
 
    }, 
 

 
    clear() { 
 
     this.wrapped.length = 0; 
 
    }, 
 
    
 
    getItem(index) { 
 
     return this.wrapped[index]; 
 
    }, 
 
    
 
    setItem(index, value) { 
 
     this.wrapped[index] = value; 
 
    } 
 
    
 
} 
 

 
var MyArrayWrapperProxyHandler = { 
 
    get: function (target, key, receiver) { 
 
     if (isArrayIndex(key)) { 
 
      return receiver.getItem(toArrayIndex(key)); 
 
     } else { 
 
      return Reflect.get(target, key, receiver); 
 
     } 
 
    }, 
 
    set: function (target, key, value, receiver) { 
 
     if (isArrayIndex(key)) { 
 
      return receiver.setItem(toArrayIndex(key), value); 
 
     } else { 
 
      return Reflect.set(target, key, value, receiver); 
 
     } 
 
    } 
 
}; 
 

 
MyArrayWrapper.prototype = new Proxy(MyArrayWrapper.prototype, MyArrayWrapperProxyHandler); 
 

 
var array = ['a', 'b', 'c']; 
 
var wrapper = new MyArrayWrapper(array); 
 

 
console.log('read:', wrapper[2] === 'c'); // true, reads from wrapped array 
 

 
wrapper[3] = 'd'; 
 
console.log('write:', array[3] === 'd'); // true, writes to wrapped array 
 
console.log('resize:', wrapper.length === 4); // true, wrapped array is resized

これは、プロキシオブジェクトをサポートする最新のブラウザを必要とし、それは手動でプロトタイプチェーンを介して他の特性(例えばthis.wrapped)を通過するReflectを使用します。それらを正しくトラップする方法が見つからなかったので、うまくいかないものがたくさんあります(たとえば、'2' in wrappedfalse)。

さらに、プロキシは直接hasItem/getItem/setItemを使用するよりもはるかに低速ですので、パフォーマンス上重要なものには使用しないことをお勧めします。彼らはまた、突然単純なfoo[0] = 'bar'は、プロキシが関与しているときにあらゆる種類の狂ったことをすることができるので、使い方が非常に混乱する可能性があります。

上記のすべてで問題がない場合は、上記のスニペットにいくつかの型を追加し、代理配列インデックスgetter/setterを持つTypeScriptコードがあることを確認してください。これは本当に「概念の証明」のほうです。JavaScriptをどれだけ押し込めるかを見てみたかっただけです。 :-P

関連する問題