Class decorators are invoked only once, during the class definition process. They do not affect subclasses directly. To decorate subclasses, you would need to individually apply the decorator to each subclass.
Currently, there are no universal triggers available to automatically execute code when a subclass extends an already decorated superclass. One workaround could involve having subclasses invoke your code when their first instance is created. This means that while
class Subclass extends Superclass {}
doesn't trigger any action, calling
new Subclass()
will activate the code, but subsequent instances won't. It may suffice for some scenarios. Here's one possible implementation:
const handleForThisClassAndForEachSubclass =
(cb: ((ctor: new (...args: any) => void) => void)) =>
(ctor: new (...args: any) => any) => {
const registry = new Set<new (...args: any) => any>();
const alreadyDecorated = Symbol();
const {[ctor.name]: newCtor} = {
[ctor.name]: class extends ctor {
constructor(...args: any) {
super(...args);
const thisCtor = this.constructor as new (...args: any) => any;
if (!registry.has(thisCtor)) {
cb(thisCtor);
registry.add(thisCtor);
}
}
}
};
cb(newCtor);
registry.add(newCtor);
return newCtor;
};
This creates a registry of constructors and calls the callback function just once for each encountered constructor. Overriding the superclass constructor ensures that actions are triggered when constructing subclasses. While the approach may seem complex, its functionality can be demonstrated as follows:
const show = (ctor: new (...args: any) => any) => {
console.log("I'm customizing this", ctor);
}
console.log("before declaring superclass")
@handleForThisClassAndForEachSubclass(show)
class Superclass {
} // I'm customizing this function Superclass()
new Superclass(); // no output
console.log("before declaring subclass")
class Subclass extends Superclass {
} // no output
console.log("before creating subclass instance")
new Subclass(); // I'm customizing this function Subclass()
console.log("before creating subclass instance")
new Subclass(); // no output
console.log("before declaring another subclass")
class Subclass2 extends Superclass {
} // no output
console.log("before creating another subclass instance")
new Subclass2(); // I'm customizing this function Subclass2()
console.log("before creating another subclass instance")
new Subclass2(); // no output
console.log("before subsubclass declaration")
class SubSubclass extends Subclass {
} // no output
console.log("before subsubclass creation")
new SubSubclass(); // I'm customizing this function SubSubclass2()
console.log("before subsubclass creation")
new SubSubclass(); // no output
The function show()
demonstrates being called once for SuperClass
at creation time and again for each subclass upon their initial instantiation. Depending on your specific requirements, substituting show
with your intended function like
guardAllNonConstructorOwnMethodsAgainstBadArguments
might yield useful results. Regardless, this method of overriding superclass constructors can lead to customized actions when constructing subclass instances. Best of luck with your application!
Link to code