Search code examples
typescriptbabeljsdecoratorbundlertypescript-5

Typescript Decorator Add Initializer is not triggered when using Babel


Today i decided to try out a Bundler, and wanted to use Babel,

Before i switched to Babel my decorators worked fine, however now i noticed that the class property addInitializers arent working anymore.

For Context, im currently building my own DI Container in Typescript.

Decorator code:

export function Inject(name: string) {
    console.log("Inject");
    let stop = true;
    return function (target: any, context: ClassFieldDecoratorContext) {

        console.log("Inject 2");
        context.addInitializer(function () {
            if (this["_dependencyBindDataList"] == undefined) {
                this["_dependencyBindDataList"] = [];
            }
            console.log("Inject 3");
            (this["_dependencyBindDataList"] as PropertyBindData[]).push({
                property: context.name as string,
                target: name,
                type: DependencyType.SINGULAR
            });
        })
    }
}

the third console log never gets triggered.

I used Two test classes for this:

class Test {
    @Inject("folderOrganisationPopulator")
    public test;

}

class Test2 {
    @Inject("test2")
    public test2;
}

and they get instanciated in their own component methods:

@Component("test")
public test(){
    return new Test();
}

@Component("test2")
public test2(){
    return new Test2();
}

They worked before i switched to Babel, so i think babel is probably configured wrong:

my babel config is:

{
  "presets": [
    [
      "@babel/env",
      {
        "modules": false,
        "targets": {
          "node": "18"
        }
      }
    ],
    "@babel/typescript"
  ],
  "sourceMaps": true,
  "plugins": ["add-import-extension",["@babel/plugin-proposal-decorators", { "version": "2023-05" }]]
}

Solution

  • The problem is with typescript implementation for decorators. Try to return your initializer function instead of adding it to the context.

    Your Decorator would look like this:

    export function Inject(name: string) {
    console.log("Inject");
    let stop = true;
    return function (target: any, context: ClassFieldDecoratorContext) {
    
        console.log("Inject 2");
        return function (this: any) {
            if (this["_dependencyBindDataList"] == undefined) {
                this["_dependencyBindDataList"] = [];
            }
            console.log("Inject 3");
            (this["_dependencyBindDataList"] as PropertyBindData[]).push({
                property: context.name as string,
                target: name,
                type: DependencyType.SINGULAR
            });
        }
    }
    

    Also fix the "this" reference