这里是一个简单的 vanilla js 实现链接,使用代理支持“虚拟”属性:
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"
每个新的“链接”都会返回一个新的 Chain 对象以保持其不可变。我一直在尝试添加类型,但无法正常工作:
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'
我是打字稿的新手,我能做到的最好的事情就是让第一个“链接”起作用:
const chain = new Chain() as Chain & { [key: string]: Chain };
chain.you.can.use.dynamic.properties.log();
// Property 'can' does not exist on type 'Chain'
我也尝试了递归类型,但没有运气:
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'
已经为此苦苦挣扎了几天,将不胜感激任何建议。