privatenumber / tsx

⚡️ TypeScript Execute | The easiest way to run TypeScript in Node.js
https://tsx.is
MIT License
9.73k stars 152 forks source link

tsx does not execute decorator initializers for optional properties with target es2021 in tsconfig.json #597

Open Gerrit0 opened 4 months ago

Gerrit0 commented 4 months ago

Acknowledgements

Minimal reproduction URL

https://github.com/Gerrit0/repros/tree/tsx-broken-decorators

Problem & expected behavior (under 200 words)

No response

Bugs are expected to be fixed by those affected by it

Compensating engineering work will speed up resolution and support the project

Gerrit0 commented 4 months ago

I should also mention that the contribution guide link is broken in the issue template

privatenumber commented 4 months ago

I don't use decorators so I don't know much about it. But the decorators transformation is handled by esbuild which has put out thorough release notes on it in the past few releases: https://github.com/evanw/esbuild/releases

I will look into this later and if I do confirm that it's more than configuration issue, it will likely be relayed to the esbuild repo.

guocailee commented 4 months ago

I have same issue with nestjs project

patryksuchowierski commented 4 months ago

I've faced same issue with the nestJS, managed to work it around with this https://github.com/dividab/tsconfig-paths/issues/243#issuecomment-1468660852 but it'd be nice to have a proper support for the decorators

privatenumber commented 4 months ago

This is a bug tracker. As per the Contribution Guide, please keep comments productive towards fixing the bug.

Feel free to investigate the problem in tsx and propose a fix.

mkvlrn-cm42 commented 2 months ago

ESBuild supporting decorators is only half the problem when it comes to NestJS - decorators are recognized and built, but there's also the extra logic somewhere in the nest CLI that detects constructor injections and adds them to the transpilation result.

That's why using the @Inject decorator on your constructors will make it work:

import { Controller, Get, Inject } from "@nestjs/common";
import { AppService } from "./app.service.js";

@Controller()
export class AppController {
  // constructor(private readonly appService: AppService) {} // this won't work
  constructor(@Inject(AppService) private readonly appService: AppService) {} // this will work

  @Get()
  getHello(): string {
    return this.appService.sayHello();
  }
}

This builds properly with ESBuild and runs as expected with tsx. Don't think there's anything to do on tsx's side.

I find this an okay compromise, you're just being explicit with your injections.

Obviously I could be extremely wrong - this is what I've learned in the past 24h or so trying things out.