Exploring the realm of Typescript decorators has led me to discover their intriguing behavior when combined with class inheritance.
Consider the following scenario:
class A {
@f()
propA;
}
class B extends A {
@f()
propB;
}
class C extends A {
@f()
propC;
}
function f() {
return (target, key) => {
if (!target.test) target.test = [];
target.test.push(key);
};
}
let b = new B();
let c = new C();
console.log(b['test'], c['test']);
The current output is:
[ 'propA', 'propB', 'propC' ] [ 'propA', 'propB', 'propC' ]
However, the expected output would be:
[ 'propA', 'propB' ] [ 'propA', 'propC' ]
This suggests that target.test
is shared among classes A, B, and C. Here's my analysis:
- When instantiating
new B()
, it triggers initialization of class A first, invoking the evaluation off
for A. Astarget.test
is undefined, it gets initialized. - Subsequently,
f
is called for class B after extending from A. At this point,target.test
in class B references the same instance as class A, resulting in the accumulation of propertiespropA
andpropB
. So far, so good. - A similar process occurs with class C inheriting from A. Despite my anticipation of a distinct
test
object for C, the shared log proves otherwise.
I am seeking insights on why this behavior persists and how I can modify f
to grant separate test
properties for A and B. Could this involve creating an "instance specific" decorator?