0

I have a c# Class

    class BaseModel
    {  
       private Dictionary<string, string> _attr;

       public string this[string propName]
       {
           get
           {
               string strReturnValue = string.Empty;
               if (this._attr.ContainsKey(propName))   
                  strReturnValue = this._attr[propName];
               return strReturnValue;
           }
           set
           {
              if (!this._attr.ContainsKey(propName))
                 this._attr.Add(propName, value);
              else
                  this._attr[propName] = value;
              // Doing something here
           }
        }

        public BaseModel(BaseModel aParent)
        {
            this._attr = new Dictionary<string, string>();
        }
    }

Basically I want to perform some code while setting the dictionary through indexer property, I cannot find a way to do this in typescript. Can anyone help me about this requirement.

  • 2
    First of all, welcome to StackOverflow. It is a good practice to begin a question with the actual question and add any relevant code samples at the end. Further, do I understand correctly that you have written this code in C# and now are trying to do something equivalent in TypeScript? – MechMK1 Nov 27 '17 at 11:08
  • Please see: https://stackoverflow.com/help/how-to-ask – wally Nov 27 '17 at 11:13

1 Answers1

2

If you are using es2015 you can use the buit-in Proxy class. This will allow you to intercept any index set/get:

class BaseModel
{
    attr : { [propName: string] : string} = {};
    getValue(name: string) : string {
        return this.attr[name] || ""
    }
    setValue(name: string, value: string) {
        this.attr[name] = value;
    }
}

var p = new Proxy(new BaseModel(), { 
    get: (target, name)=> target.getValue(<string>name),
    set: (target, name, value)=> {
        target.setValue(<string>name, value)
        return true;
    }
});

console.log(p["unset"]); //Output ""
p["test"] = "set"
console.log(p["test"]); //Output set

Note All access to the object must be done through the proxy, and since you cannot extends a Proxy (a limitation of JS) you can't really use this for a base class (as the name suggests you may want to). You could make the constructor private and have a static create method that ensures all objects are created using the proxy, which would make this solution usable:

class BaseModel
{
    protected constructor (){

    }
    attr : { [propName: string] : string} = {};
    getValue(name: string) : string {
        return this.attr[name] || ""
    }
    setValue(name: string, value: string) {
        this.attr[name] = value;
    }
    public static wrap<T extends BaseModel>(value: T): T {
        return new Proxy(value, { 
            get: (target, name)=> target.getValue(<string>name),
            set: (target, name, value)=> {
                target.setValue(<string>name, value)
                return true;
            }
        });
    }
}
class Derived extends BaseModel {
    protected constructor (){
        super();    
    }
    public static createDerived(): Derived {
        return BaseModel.wrap(new Derived());
    }
}
var p =  Derived.createDerived();
console.log(p["unset"]); //Output ""
p["test"] = "set"
console.log(p["test"]); //Output set
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357