I'm really spending a lot of time pointing out a genuine issue in your design, so the accusations are a bit of of place. I'm not sure where I'm failing at communicating the problem that you don't seem to understand.
Here is a more spelled our example. I assumed someone with your experience would have been able to connect the dots.
Not proofed because I really don't have time.
class Foo {
#bar;
get bar() {
return this.#bar;
}
initBar(bar) {
if (this.#bar !== undefined) throw Error();
this.#bar = bar;
}
static isFoo(foo) {
return #bar in foo;
}
static asClonePayload(foo) {
return { bar: foo.#bar };
}
static fromClonePayload(data) {
const foo = new Foo();
foo.initBar(data.bar);
return foo;
}
}
class Bar {
#foo;
constructor(foo) {
this.#foo = foo;
}
get foo() {
return this.#foo;
}
static isBar(bar) {
return #foo in bar;
}
static asClonePayload(bar) {
return { foo: bar.#foo };
}
static fromClonePayload(data) {
return new Bar(data.foo);
}
}
const registry = new CloneRegistry([
['Foo', {
is: value => Foo.isFoo(value),
to: value => Foo.asClonePayload(value),
from: value => Foo.fromClonePayload(value),
}],
['Bar', {
is: value => Bar.isBar(value),
to: value => Bar.asClonePayload(value),
from: value => Bar.fromClonePayload(value),
}],
]);
const foo = new Foo();
const bar = new Bar(foo);
foo.initBar(bar);
Foo.isFoo(foo) && foo.bar.foo === foo; // true
// No way to implement this with your proposed `from` registry API.
const foo2 = registry.clone(foo);
Foo.isFoo(foo2) && foo2.bar.foo === foo2; // should be true