2016-08-12 116 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

相关问题