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

Closure Compiler incompatible with TypeScript method decorators #2065

Closed
btraut opened this issue Oct 6, 2016 · 14 comments
Closed

Closure Compiler incompatible with TypeScript method decorators #2065

btraut opened this issue Oct 6, 2016 · 14 comments

Comments

@btraut
Copy link

btraut commented Oct 6, 2016

It appears that the use of method decorators from TypeScript fall flat on their face when run through Closure Compiler due to the use of function names being passed as strings.

I have an AuthStoreImpl class that declares a getUser method that has an @autoSubscribe decorator. TypeScript compiles this by adding this after the class definition:

__decorate([
       resub_1.autoSubscribe
], AuthStoreImpl.prototype, "getUser", null);

Obviously I can use @nocompile to prevent any file that uses a decorator to remain untouched, but that kind of defeats the purpose. What I would really love to do is to add an annotation to the getUser method to prevent renaming of just that method, but I was disappointed to read that there's no plans to allow this granularity.

If I may ask, what's the reason behind the decision to not allow inline annotations on specific symbols? It seems this would empower users to work around a lot of issues with Closure Compiler being to aggressive, especially when those users don't have complete control over their code (as is the case with code compiled by TypeScript).

@Dominator008
Copy link
Contributor

Can you provide more detail on how Closure Compiler failed on the TypeScript output?

@btraut
Copy link
Author

btraut commented Oct 6, 2016

Sorry, should've provided this initially.

The issue here is that Closure Compiler renamed my getUser() method to d() or something of the sort, but because it doesn't modify strings, it left TypeScript's decorator to reference "getUser". Deep inside the __decorate stack trace, it tries to find the "getUser" function and no such function exists.

@ChadKillingsworth
Copy link
Collaborator

ChadKillingsworth commented Oct 6, 2016

Closure-compiler can rename string references safely now with goog.reflect.objectProperty:

__decorate([
       resub_1.autoSubscribe
], AuthStoreImpl.prototype,
goog.reflect.objectProperty("getUser", AuthStoreImpl.prototype),
null);

That should safely compile.

edit: assuming I inferred the types correctly that is

@MatrixFrog
Copy link
Contributor

@mprobst probably knows of a good way to handle this.

@mprobst
Copy link
Contributor

mprobst commented Oct 6, 2016

@evmar is the expert. We're maintaining a tool called tsickle (http://github.com/angular/tsickle) that rewrites TypeScript output to be Closure compatible (including type annotations, actually). I'm not sure if we have something to fix this renaming issue with method decorators specifically, but it shouldn't be too hard to fix, I guess?

Alternatively, you could also ask the MS folks to change their emit to avoid quoting the method, e.g.

AuthStoreImpl.prototype.getUser = __decorate([
       resub_1.autoSubscribe
], AuthStoreImpl.prototype.getUser, null);

@btraut
Copy link
Author

btraut commented Oct 6, 2016

I would love if the decorator didn't use strings, and I'll likely also reach out to the TS team as well.

As for using goog.reflect, I don't control TypeScript's output, so I have no opportunity to implement that solution. If tsickle could do that, it'd be great. I suppose I'd have to reach out to those folks to support decorators then?

@mprobst
Copy link
Contributor

mprobst commented Oct 6, 2016

@btraut please do file an issue against tsickle. Depending on the response from MS, this is something we should do.

@btraut
Copy link
Author

btraut commented Oct 6, 2016

Posted over on the TS issues as well:
microsoft/TypeScript#11435

@rbuckton
Copy link

rbuckton commented Oct 6, 2016

@btraut One option available to you out of the box is to write a custom __decorate helper that calls goog.reflect and use that one instead.

@btraut
Copy link
Author

btraut commented Oct 6, 2016

Sounds like the function name, "getUser" in my case eventually gets passed into Object.defineProperty, and must be a string as such.

@mprobst
Copy link
Contributor

mprobst commented Oct 6, 2016

@rbuckton the problem is that goog.reflect.objectProperty must take a string literal as its first input, it's a compiler intrinsic.

@rbuckton
Copy link

rbuckton commented Oct 6, 2016

Ah, I see.

@ChadKillingsworth
Copy link
Collaborator

I'm going to close this issue as it doesn't appear to be anything the compiler itself can handle.

@btraut
Copy link
Author

btraut commented Oct 6, 2016

Thanks for the help, @ChadKillingsworth.

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

No branches or pull requests

6 participants