2016-08-12 120 views
3

有什麼辦法來委派索引屬性來打字稿一員?我正在編寫一個包裝器,並且我想將索引屬性委託給我要包裝的對象。有什麼辦法可以在typescript中委託索引屬性?

喜歡的東西:

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代碼這樣的結構。有在JavaScript沒有辦法界定。只要任何屬性設置時調用的類捕獲所有的getter/setter。

我能得到的最接近的是通過定義在類hasItemgetItemsetItem方法,然後包裝每個實例的該類在ES2015 Proxy對象的原型,其代理的所有get S和set小號到該實例的屬性。

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

這需要有用於代理對象支持一個現代瀏覽器,它使用通過Reflect原型鏈手動通過其他性質(例如this.wrapped)。有很多東西不工作(例如'2' in wrappedfalse),因爲我沒有找到一個方法來捕獲那些正確。

而且,代理是不是直接使用hasItem/getItem/setItem慢得多,所以我不建議將其用於任何性能的關鍵。它們也可以是很混亂使用,因爲突然一個簡單foo[0] = 'bar'可以做各種瘋狂的事情時有參與代理。

如果您能夠接受上述所有,那麼肯定的,添加一些類型上面的代碼中,你有一個委託數組索引的getter/setter打字稿代碼。這實際上更像是一種「概念驗證」,我只是想看看你能推多少JavaScript。 :-P

相關問題