I got a custom decorator that wraps the constructor to do other stuffs when instantiating code.
When I'm trying to inject stuffs into the constructor, everything is undefined.
Injected stuffs are undefined
This issue is caused because InversifyJS adds some metadata to the constructor. You are creating a new constructor and the metadata is lost. You need to manually copy the metadata from the original constructor to the new constructor. We can use the reflect-metadata API:
const {Container, injectable, inject, named} = inversify
function logClass(target: any) {
// save a reference to the original constructor
var original = target;
// a utility function to generate instances of a class
function construct(constructor, args) {
var c : any = function () {
return new constructor(...args);
}
c.prototype = constructor.prototype;
return new c();
}
// the new constructor behaviour
var newConstructor : any = function (...args) {
console.log("New: " + original.name);
return construct(original, args);
}
// copy prototype so intanceof operator still works
newConstructor.prototype = original.prototype;
// Copy metadata
var metadataKeys = Reflect.getMetadataKeys(target);
metadataKeys.forEach((metadataKey) => {
var metadataValue = Reflect.getMetadata(metadataKey, target);
Reflect.defineMetadata(metadataKey, metadataValue, newConstructor);
});
// return new constructor (will override original)
return newConstructor;
}
interface IPerson {
say: () => void;
}
@injectable()
class Person implements IPerson {
say() {
console.log('hello folks');
}
}
let personType = Symbol('Person');
let stuffType = Symbol('Stuff');
@injectable()
@logClass
class Stuff {
constructor(@inject(personType) private person: IPerson) {
console.log(person);
}
do() {
this.person.say();
}
}
let container = new Container();
container.bind<IPerson>(personType).to(Person);
container.bind<Stuff>(stuffType).to(Stuff);
let stuff = container.get<Stuff>(stuffType);
stuff.do(); // hello folks
Most helpful comment
This issue is caused because InversifyJS adds some metadata to the constructor. You are creating a new constructor and the metadata is lost. You need to manually copy the metadata from the original constructor to the new constructor. We can use the reflect-metadata API: