I have class decorator which ensures that the class remains a singleton.
interface Type<T = any> extends Function {
new (...args: any[]): T;
}
function Singleton() {
let instance: Object;
return function <SingletonFunction extends Type>(
constructor: SingletonFunction
) {
return <SingletonFunction>class {
constructor(...args: any[]) {
if (instance) {
return instance;
} else {
instance = new constructor(...args);
Object.setPrototypeOf(instance, constructor);
return instance;
}
}
};
};
}
When I use this decorator on a class like this,
@Singleton()
class TestSingleton {
private field: any;
private field2 = Math.random();
constructor(args: any[]) {
this.field = args.reduce((acc, ele) => {
return acc + ele;
}, 0);
}
}
const x = new TestSingleton([1, 2, 3, 4, 5, 6]);
const y = new TestSingleton([6, 7, 8, 9, 1]);
console.log(x === y); // true
console.log(x instanceof TestSingleton); // false
The instanceof
operator does not work, I can not figure out what I am missing here.
2
Answers
Cómo yo voy empezando en esto quisiera saber para que es el decorado ,el síguele ton,args,any,singeletonfunction,super,this,elese ,class
Ignoring the attempt to
Object.setPrototypeOf(instance, constructor)
, the problem is withinstance = new constructor(...args);
. This calls the old (wrapped, decorated) constructor, which returns an object inheriting from the old.prototype
. However your decorator completely replaces theTestSingleton
class (which it must, to overwrite the constructor), andinstanceof TestSingleton
will therefor check inheritance against the new (returned)TestSingleton.prototype
object.The conventional approach is to just return a
class
that inherits from the original (decorated) class, and have the constructor return instances of the subclass (as it creates them by default, if you didn’t have your singletoninstance
code overriding the constructor return value).However, this creates an unnecessary extra prototype object and unnecessary extra prototype chain link. I would rather recommend to return a
class
(or simplefunction
) that has exactly the same prototype as the decorated one: