typescripttypescript2.4

Typescript: Using array notation to get items from class


I have class called Candles and a class called Candle. Candles has a property list that contains an array of Candle.

class Candles
{
  public list: Array<Candle>;
}

class Candle
{
  public date: number;
  public high: number;
  public low: number;
  public open: number;
  public close: number;
  public volume: number;
}

I want list to encapsulate with the Candles class. For example,

const candles = new Candles();
candles[3] === candles.list[3];

I want candles[3] to return candles.list[3]

I also want to use map. Example:

candles.map(function(candle: Candle) {
    console.log(candle.high);
});

Solution

  • You can intercept and forward calls to inner list using ES6 Proxy:

    class Candles {
      public list: Candle[] = [];
    
      constructor() {
        return new Proxy(this, {
          get(target, propertyKey) {
            console.log('getting ', propertyKey);
            if (propertyKey in target) {
              console.log('own property');
              return target[propertyKey]
            }
    
            console.log('forward to inner list');
            const property = target.list[propertyKey];
            if (typeof property === "function") {
              return property.bind(target.list);
            }
    
            return property;
          }
        });
      }
    }
    

    To inform the compiler that Candles can be used as an Array add following definition:

    interface Candles extends Array<Candle> { }
    

    And now all the array goodies (e.g. push, foreach, map...) can be applied to Candles:

    const candles = new Candles();
    candles.push({ low: 1 } as Candle);
    
    console.log(candles[0] === candles.list[0]); //true
    candles.forEach(c => console.log(c));
    

    Demo in playground.