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

Compile-time meta-data #54672

Closed
5 tasks done
hydroper opened this issue Jun 16, 2023 · 13 comments
Closed
5 tasks done

Compile-time meta-data #54672

hydroper opened this issue Jun 16, 2023 · 13 comments
Labels
Out of Scope This idea sits outside of the TypeScript language design constraints Suggestion An idea for TypeScript

Comments

@hydroper
Copy link

hydroper commented Jun 16, 2023

Suggestion

πŸ” Search Terms

Meta-data, definition meta-data

βœ… Viability Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • This wouldn't change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

⭐ Suggestion

Enable optionally adding compile-time meta-data to a specific definition, which is only interpreted depending on a compiler option. The meta-data does not affect code generation and is erased completely in runtime, at least in TypeScript's Compiler. However, a transform that a TypeScript Compiler API user writes can emit customized code based in that meta-data.

This could be useful for TypeScript Compiler API users that need to attach data to definitions, such as the name of a natively exported function (FFI) and then transform code based on that meta-data.

As for the name visibility, I'd recommend only declaring this Metadata decorator name in the decorator scope; e.g. a decorator consisting of a Metadata call, and this would only be treated as meta-data if the allowMetadata compiler option is on. The current script can override the Metadata name.

This proposal isn't the same as https://github.com/tc39/proposal-decorator-metadata: they're not accessible from the runtime.

πŸ“ƒ Motivating Example

If a compiler option allowMetadata is true, Metadata decorators are allowed in any definition, including class, class block definitions, interface and more. The Metadata name should be similiar to the type annotations Record and NonNullable.

@Metadata({ffi: 'com.adobe.air.C'})
class C {
}

πŸ’» Use Cases

FFI for compiler API users. I think an existing workaround is to use very specific comments such as //!metadata=com.adobe.air.C and check if they belong to a definition, but that can be problematic if the definition already has doc comments applied to it, e.g.:

//!metadata=com.adobe.air.util.f
/**
 * Does something.
 */
declare function f(): void;
@hydroper hydroper changed the title Compile-time meta-data applied to a definition Compile-time meta-data Jun 16, 2023
@fatcerberus
Copy link

@Metadata({ffi: 'com.adobe.air.C'})

This is decorator syntax, and TS already has emitDecoratorMetadata. Are you talking about something else?

I'm also confused because you say

The meta-data does not affect code generation and is erased completely in runtime.

What do you want the compiler to do with this metadata, exactly, if it doesn't affect the output? This feature request seems underspecified...

@hydroper
Copy link
Author

hydroper commented Jun 16, 2023

@fatcerberus I didn't exactly want to mean it affects the output. It can affect the output depending on who uses the TypeScript Compiler API and what they are going to do with the symbols emitted by the compiler.

The decorator I've demonstrated shouldn't work as an ECMAScript decorator exactly. And it's only treated as a meta-data decorator depending on the allowMetadata option above, avoiding breaking existing programs.

@hydroper
Copy link
Author

Added:

However, a transform that a TypeScript Compiler API user writes can emit customized code based in that meta-data.

@fatcerberus
Copy link

Thanks for clarifying.

Hmm, I don't know that it's feasible to use the decorator syntax for this though. Someone could very well have defined a real ES decorator called Metadata.

@hydroper
Copy link
Author

hydroper commented Jun 16, 2023

@fatcerberus I guess the allowMetadata compiler option above would solve that problem. It'll also be lexically similiar to the special structural types like Record<K, V> and NonNullable<T>.

@DanielRosenwasser
Copy link
Member

This feature would agree with the rest of TypeScript's Design Goals.

Unfortunately this proposal violates:

Use a consistent, fully erasable, structural type system.

Other tools are free to consume TypeScript syntax and perform whatever transformations they need to though. This can even be done by using the TypeScript APIs.

Otherwise, https://github.com/tc39/proposal-decorator-metadata is on our plan for TypeScript 5.2.

@DanielRosenwasser DanielRosenwasser added the Out of Scope This idea sits outside of the TypeScript language design constraints label Jun 16, 2023
@hydroper
Copy link
Author

hydroper commented Jun 16, 2023

@DanielRosenwasser But, yes, it's fully erasable. The meta-data I've been demonstrating are constant (compile-time) values associated to definitions purely for developers using the compiler API. This meta-data cannot be accessed from the script itself.

I don't think it's out of scope.

@hydroper
Copy link
Author

Otherwise, https://github.com/tc39/proposal-decorator-metadata is on our plan for TypeScript 5.2.

This proposal seems unrelated as it's about adding meta-data that can be accessed at runtime.

@MartinJohns
Copy link
Contributor

Then there's still this point:

Preserve runtime behavior of all JavaScript code.

If the decorator is removed, then the runtime behavior of the JavaScript code is not preserved anymore.

@hydroper
Copy link
Author

Then I guess a new syntax that does not use the decorator syntax could be used, that is specific to TypeScript? Anyway, the option allowMetadata shown above would be false by default, not breaking existing programs.

@hydroper
Copy link
Author

hydroper commented Jun 16, 2023

Another thing to consider is that if the decorator is overriden by the script, then this Metadata decorator can be not removed. E.g.:

@Metadata() // 'Metadata' is undefined; remove it
var x = 0

And:

var Metadata = () => {}
@Metadata() // 'Metadata' exists; don't remove it
var x = 0

This is of course if allowMetadata is on.

@DanielRosenwasser
Copy link
Member

In that case, maybe #2900 is relevant.

@typescript-bot
Copy link
Collaborator

This issue has been marked as "Out of Scope" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Jun 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Out of Scope This idea sits outside of the TypeScript language design constraints Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants