Open EdwardDrapkin opened 5 years ago
Duplicate #2900?
It's a similar suggestion, but of a much smaller scope.
In my mind, annotations should be attachable to almost anything that is a compiler node: a class, a function, a class field, a local variable, an interface, a field assignment, etc.
An example of something that I think this would make much easier than is currently possible that the other suggestion wouldn't necessarily help with: Let's say you're working in a large hypothetical framework and have an interface hierarchy of Animal
> FourLegs
> Canine
> Dog
> GermanShepherd
. In one of your controllers, you ask for an Animal
from the framework. With annotations, you could annotate class Fluffy implements GermanShepherd
and allow the framework to register the class as a qualifying injection for that entire hierarchy and provide you Fluffy
.
Another case: adding a SinceVersion
, Commercial
, IEOnly
, whatever annotations to source code and building a tool to compile separate SDKs for different targets from the same code.
It doesn't appear that the other suggestion would enable this, because it doesn't mention that the functions are specifically tied to the compiler API and can potentially output new code to be compiled in the same compile step. Maybe I should be more clear in the original issue, I will clarify.
I belive this is great, as way to perform custom code transformations at compile time, not at runtime!
By the way, to circumvent the limitation of reflection we could make TS compiler to inject JS annotations with type information?
Hey, any update on this? Would be great to have this.
Search Terms
annotation compile time decorator
Suggestion
The way that decorators are currently implemented in TypeScript mirrors their functionality in JS in that they exist at run time and work on run time objects. Because of TypeScript's transpiled nature, a tremendous amount of important metadata is lost by the time decorators are run. Even with the
reflect-metadata
package, important type information is lost. This represents a nearly insurmountable hurdle in developing high quality software in some extremely important areas.Consider the case of dependency injection. Any of the TS containers require manually wiring the container together and, even worse, a healthy amount of invocation-site syntactical noise. I come from a Java background, and I think about the Spring DI container, where there is no manual configuration and there is no invocation-site noise, because there's no invocation site. The container is constructed at compile time based on annotations and classpath discovery, which leads to a much smoother developer experience. Building a DI container in TS with that level of developer ergonomics would be a pretty herculean task.
Consider the case of automatically generating webservice code from static model definitions. I'm not even sure if this is currently possible, but it's a feature that developers coming from mature web frameworks expect.
I believe that these two things, as well as a myriad of other cases where AOP is well applied, are important pieces that should be available in the TS ecosystem. TS is a compiled language and constraining the metaprogramming (decorator) facilities to what is available in JS code prevents these tools from being developed, or at least greatly slows their progress.
To this aim, I would like to suggest the addition of compiler annotations: functions that run on compiler nodes at compile time, have the ability to output additional code and otherwise interact with the compiler, but do not have the ability to mutate the compiler nodes. These suggested annotations would only ever be compile-time metadata, whereas decorators are run-time mutators. Adding or removing decorators will change run time behavior, but annotated code should always compile to the same code whether annotations are added or removed. Annotated code may inform a framework that other code is to be generated, but are otherwise completely erased in the JS code and exist only as a compiler facility.
I believe it's fully possible to do all of this now with a custom compiler step that outputs generated code, and it may even be possible to integrate with the language server so that code doesn't have to constantly be generated. I don't believe this violates any of the design goals/non-goals of TS, as the annotations don't change the behavior (or emitted JS) of the annotated code, merely provide an easier facility for library developers to interact with TS and take advantage of the compile step.
I don't want to presume to recommend a syntax or an API to this feature.
To summarize, annotations would:
DisableLint
would be allowed anywhere, but aInjectable
annotation would likely want to narrow its scope)