Reputation: 2852
A couple of years ago, I wanted figure how to create a type check for class A
that returns true
only for objects instantiated by new A()
. For this, I wrote the class like this:
class A {
static #instances = new WeakSet();
static isInstance (value) {
return A.#instances.has(value);
}
constructor () {
if (new.target === A) {
A.#instances.add(this);
}
}
}
Any instance of a class that extends A
thus would return false
when passed to A.isInstance
. But, then I realized that this can be faked by using Reflect.construct(B, [], A)
. What I did, then, was create a proxy whose construct
trap would only pass A
as newTarget
if it met some condition. I've been trying to recall what that condition was, but while experimenting to rediscover it, I'm beginning to think that my old solution might not've worked.
Is there some way to achieve my desired effect here?
Upvotes: -1
Views: 77
Reputation: 23607
Seems there's no obvious clean way to do it
Reflect.construct
to catch when the prototype is overriddenclass A {
static #instances = new WeakSet();
static isInstance (value) {
return A.#instances.has(value);
}
constructor() {
if (new.target === A) {
try{
throw new Error;
}catch(e){
// parse function names (in FF the stack is different)
const [a, b] = e.stack.match(/\w+(?=\s*\()/gm);
const fn = eval(b);
if(fn?.toString().includes('extends A')) return;
}
A.#instances.add(this);
}
}
}
class B extends A{}
const b = Reflect.construct(B, [], A);
console.log(A.isInstance(b));
const a = new A;
console.log(A.isInstance(a));
Upvotes: 0