Skip to content

Compile-time meta-dataΒ #54672

Description

@hydroper

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;

Activity

  1. changed the title [-]Compile-time meta-data applied to a definition[/-] [+]Compile-time meta-data[/+] on Jun 16, 2023
  2. fatcerberus commented on Jun 16, 2023

    @fatcerberus

    @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...

  3. hydroper commented on Jun 16, 2023

    @hydroper
    Author

    Bruce Pascoe (@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.

  4. hydroper commented on Jun 16, 2023

    @hydroper
    Author

    Added:

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

  5. fatcerberus commented on Jun 16, 2023

    @fatcerberus

    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.

  6. hydroper commented on Jun 16, 2023

    @hydroper
    Author

    Bruce Pascoe (@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>.

  7. DanielRosenwasser commented on Jun 16, 2023

    @DanielRosenwasser
    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.

  8. hydroper commented on Jun 16, 2023

    @hydroper
    Author

    Daniel Rosenwasser (@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.

  9. hydroper commented on Jun 16, 2023

    @hydroper
    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.

  10. MartinJohns commented on Jun 16, 2023

    @MartinJohns
    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.

  11. hydroper commented on Jun 16, 2023

    @hydroper
    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.

  12. hydroper commented on Jun 16, 2023

    @hydroper
    Author

    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.

  13. DanielRosenwasser commented on Jun 16, 2023

    @DanielRosenwasser
    Member

    In that case, maybe #2900 is relevant.

  14. typescript-bot commented on Jun 23, 2023

    @typescript-bot
    Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Out of ScopeThis idea sits outside of the TypeScript language design constraintsSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions