Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support emitDecoratorMetadata use refleact-metadata #509

Closed
wants to merge 7 commits into from

Conversation

jaxchow
Copy link

@jaxchow jaxchow commented Nov 6, 2020

Command line add -- refleat metadata supports emitdecoratormetadata to override __decorate method, add __metadata record type information description.
After compiling, please see the snapshot internal/bundler/snapshots/snapshots_ts.txt-> TestTypeScriptDecoratorsMetadata

@wxs77577
Copy link

wxs77577 commented Nov 6, 2020

Great job!

@evanw
Copy link
Owner

evanw commented Nov 7, 2020

Sorry but it's not possible to implement this correctly without type information, and re-implementing TypeScript's type checker in esbuild is deliberately out of scope. This is why emitDecoratorMetadata is not supported.

Even though it's sometimes possible to fill in the correct types (e.g. when the type is literally number you can know to fill in Number), this isn't a general solution and won't work on all code. For example, esbuild would have no idea what to use for a type alias imported from another file. Also TypeScript's type system is Turing-complete and can perform arbitrary computation. Here's a random example:

class Foo { x = 123 }
type T = Foo extends { x: number } ? number : boolean
function fn(obj: any, key: string) {}
class Test { @fn foo(t: T) {} }

This generates __metadata("design:paramtypes", [Number]) if x = 123 and __metadata("design:paramtypes", [Boolean]) if x = 'abc'. Tracing the type of x through all of those type expressions requires a replica of TypeScript's type system.

I won't be adding partial support for emitDecoratorMetadata to esbuild because it's not possible to implement this correctly without TypeScript's type system.

@evanw
Copy link
Owner

evanw commented Nov 15, 2020

I'm closing this PR for the reasons stated above.

@atifsyedali
Copy link

@evanw Would it possible to support this PR behind a flag -- like experimentalEmitDecoratorMetadata -- on esbuild itself?

Even though it's sometimes possible to fill in the correct types (e.g. when the type is literally number you can know to fill in Number), this isn't a general solution and won't work on all code.

While we totally understand your point above, I am frequently looking at large codebases (right now, one is at ~450k LoC and another at ~150k) and the decorators are most used with primitive types or classes. The biggest problem will be if the class is defined in another file.

If the experimental flag doesn't work for you, maybe another option is to have a JS plugin callback type for resolving decorator metadata. This would only get invoked on decorators (don't even need regex filters) so the hit would be minimal -- only if there are decorators in the file.

A third option would be some form of an AST transformer plugin capability, but as you mention in #111 (comment) this is high-risk to the project.

I just want to point out how sorely needed esbuild is on large projects that unfortunately use libraries like TypeORM (many!), or NestJS (also many!), or one of the more than 10,846 projects that rely on reflect-metadata (https://www.npmjs.com/package/reflect-metadata).

@sod
Copy link
Contributor

sod commented Sep 27, 2021

@evanw are we allowed to fork esbuild and write a plugin based on it? So someone could reuse your parser and serializer, but write a transformation that only transpiles annotations? Then this feature doesn't need to be in esbuild and we could add as a plugin.

There are already plugins that do this, like https://github.com/anatine/esbuildnx, but as far as I see, all of them just bail into original typescript, which is super slow. And they transpile the entire file. It would be nice to have a plugin written in go based on the work you already did that only transforms decorators as seen in https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata

Edit: I see the MIT license. Maybe I gonna try it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants