Recursive method chaining with Proxy in Typescript

86 Views Asked by At

Here is a simple vanilla js implementation of chaining with the use of Proxy to support "virtual" properties:

const ChainHandler = {
  get(target, prop, receiver) {
    if (prop in target) {
      return Reflect.get(target, prop, receiver);
    }
    return target.link(prop);
  }
};

class Chain {
  constructor(links = []) {
    this.links = links;
    return new Proxy(this, ChainHandler);
  }

  link(next) {
    return new Chain([...this.links, next]);
  }

  log() {
    console.log(this.links.join("-"));
  }
}

const chain = new Chain();

chain.you.can.use.dynamic.properties.log();
// logs "you-can-use-dynamic-properties"

Every new "link" returns a new Chain object to keep it immutable. I've been trying to add types, but can't get it to work:

const ChainHandler: ProxyHandler<Chain> = {
  get(target, prop, receiver) {
    if (prop in target) {
      return Reflect.get(target, prop, receiver);
    }
    return target.link(prop as string);
  }
};

class Chain {
  private links: string[];

  constructor(links: string[] = []) {
    this.links = links;
    return new Proxy(this, ChainHandler);
  }

  link(next: string) {
    return new Chain([...this.links, next]);
  }

  log() {
    console.log(this.links.join("-"));
  }
}

const chain = new Chain();

chain.you.can.use.dynamic.properties.log();
// Property 'you' does not exist on type 'Chain'

I am new to typescript and the best I've been able to achieve is getting the first "link" to work:

const chain = new Chain() as Chain & { [key: string]: Chain };
chain.you.can.use.dynamic.properties.log();
// Property 'can' does not exist on type 'Chain'

I also tried a recursive type, but no luck:

type ProxiedClass<C> = C & { [key: string]: ProxiedClass<C> };
const chain = new Chain() as ProxiedClass<Chain>;
chain.you.can.use.dynamic.properties.log();
// Property 'can' does not exist on type 'Chain'

Been struggling with it for a couple of days already, will appreciate any advice.

0

There are 0 best solutions below