Is there a way to delegate an index property in typescript?

Is there a way to delegate an index property to a member in typescript? I am writing a wrapper and I would like to delegate the index property to the object that I am wrapping.

Sort of:

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;
    }
}
+4
source share
1 answer

TypeScript does not allow this because it cannot generate JavaScript code for such a construct. In JavaScript, there is no way to define a catch-all setter / setter in a class that is called whenever any property is set.

The closest I could get is to define methods hasItem, getItemand setItemin the class, and then wrap each instance ES2015 Proxy, get 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
Hide result

Proxy, Reflect (, this.wrapped) . , (, '2' in wrapped - false), .

, - , , hasItem/getItem/setItem, - . , foo[0] = 'bar' , .

, , TypeScript getter/setter. " ", , JavaScript.:-P

+2

Source: https://habr.com/ru/post/1651116/


All Articles