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

Feature request: Meta-Programming Hooks / Active Decorators #13252

Closed
KnisterPeter opened this issue Jan 2, 2017 · 9 comments
Closed

Feature request: Meta-Programming Hooks / Active Decorators #13252

KnisterPeter opened this issue Jan 2, 2017 · 9 comments
Labels
Needs More Info The issue still hasn't been fully clarified

Comments

@KnisterPeter
Copy link
Contributor

Problem

Currently meta-programming with TypeScript is not ideal. There are a lot of features which support meta-programming but there is a lot of room for getting better.
This feature request targets code generation based on rules/declarations and meta information.

I've written pretend and realized that its not syntactically good to use decorators (as meta-information) to drive code generation.
But it could be quite intuitive for developers to do so.
The current limitations are the following:

  • Interfaces could not be target for decorators
  • Classes (which could be decorated) must have methods with body, but the body is not necessary since it is generated and only target for the meta-data
  • Empty method bodies with return types are considered failure for linters and the tsc
  • Even if interfaces could be decorated, they are not part of the emitted code (which is okay)

Solution / Idea

Allow for decorating interfaces.
Probably not only interfaces but a syntactic extension (e.g. #decorator()) to annotate other code as well (e.g. class properties, functions, variables, ...)

These decorators could then be used as hooks into the tsc code emitter and drive code generation.
With this feature meta-programming would get a lot gain, since valid typescript code could be annotated and valid js-code could be emitted. E.g. Interfaces could generate classes.

Something like active annotations like in xtend would be a good start.

If this idea would be considered acceptable I would be glad to contribute more examples and better explanations.

@calebboyd
Copy link

Just a note -the syntax suggestion is in an EcmaScript proposal https://github.com/tc39/proposal-private-fields

@KnisterPeter
Copy link
Contributor Author

Yes, but not for decorators. The syntactic distinction should be quite easy.

@aluanhaddad
Copy link
Contributor

When would this emit happen? Because interfaces have no associated output artifacts, would this take place entirely within a single compilation operation?

@zpdDG4gta8XKpMCd
Copy link

zpdDG4gta8XKpMCd commented Jan 2, 2017

look at the code rewrites idea:

#11536 closed in favor of #4892

@mhegazy
Copy link
Contributor

mhegazy commented Jan 9, 2017

Decorators do not change the type. and interfaces do not get emitted. so not sure i understand the suggestion. can you elaborate.

@mhegazy mhegazy added the Needs More Info The issue still hasn't been fully clarified label Jan 9, 2017
@KnisterPeter
Copy link
Contributor Author

KnisterPeter commented Jan 10, 2017

What I had in mind is a step in the compile and emit process which processes this kind of decorators and executes them. These decorators have an API into the emit process and could emit code.

For example this annotated interface:

#Inspect()
interface BusinessObject {
  ...
}

function Inspect(decl, codeGenerator) {
  const clazz = codeGenerator.createClass(decl.name + 'Impl');
  clazz.addMethod('toString', `
    return `${decl.attributes...}`;
  `);
}

Could produce this typescript code:

class BusinessObjectImpl implements BusinessObject {

  public toString(): string {
    return `...some output based on the attributes...`
  }

}

The description in the xtend documentation is quiet good I think even though its java specific. But the idea is the same.

I think its easy to understand and write meta-code if its in the same language and fits naturally.
Macros fall into the same principle but are a bit harder to get your head around them (just my thoughts).

Does that help a bit more?

@aluanhaddad
Copy link
Contributor

Java interfaces are manifest at runtime (sans generic types). TypeScript interfaces are not.

@KnisterPeter
Copy link
Contributor Author

I don't talk about runtime interfaces. But for the ts compiler there are interfaces and there could be a compile phase which processes decorators. Java is ist for example of semantic and syntax. This proposal does not have anything to do with java.

@mhegazy mhegazy closed this as completed Apr 21, 2017
@shaunc
Copy link

shaunc commented Oct 6, 2017

I have a repeating pattern in my code: I have objects related to other objects backed by a datastore; privately I store object & id. I have "sync" accessor/manipulator that can get object if present and set either id or object; "sync" get throws error if no object loaded by id is present. "async" versions actually do database lookup.

I wanted to write a mixin for this, but the name of the member functions should reflect the name of the relationship. Some sort of metaprogramming interface would allow this to happen. To be clear, as @KnisterPeter suggests, the translation would happen at compile-time, so that at runtime no type info need be preserved. (See the "macro" facility of nim, for example, but no need AFAIK for my use case to support arbitrary manipulation of AST -- interfaces to define types as proposed would be sufficient.)

UPDATE -- ah -- sorry -- in my hast didn't notice issue had been superseded. Going to new thread....

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Needs More Info The issue still hasn't been fully clarified
Projects
None yet
Development

No branches or pull requests

6 participants