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.