0

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);
});

4 Answers 4

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

You can't change the behavior of the indexing operation in Typescript because Javascript does not support this either. What you could do is create a type taht extends the standard array, as described in this question

Comments

0

What you want there is operator overloading. Typescript does not have support for it.

You can learn more about the reasoning why this is the case in the github issue threads: https://github.com/Microsoft/TypeScript/issues/2319 https://github.com/Microsoft/TypeScript/issues/5407

Comments

0

Here's what I did:

class Candles extends Array<Candle>
{
  constructor(candles: Array<Candle.Data>) {
    super(...candles.map((candle) => new Candle(candle as Candle.Data)));
    Object.setPrototypeOf(Candles, Object.assign(Array.prototype, Candles.prototype));
  }
}

I got rid of list and just extended Array<Candle>. I also added Object.setPrototypeOf(Candles, Object.assign(Array.prototype, Candles.prototype)); to use the Array methods along with Candles's method

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.