-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Hi, I was sent this way from tc39/proposal-decorators#489 because the decorators proposal has an extensions page that discusses annotations that I believe could be more suitable for metadata.
I don't have any objections to this (repo's) proposal, per se, but I think one of the thing that the extensions annotations proposal and my subsequent proposal based on that does well is make the runtime effects of annotations very minimal.
This makes those proposals more suitable for type inference / type-checking systems, because no functions are (usually) executed at runtime, making them ideal for static analysis, whereas this proposal has a larger runtime cost. So while this current proposal-decorator-metadata is not suitable as a static typing system for TypeScript / Flow, what I'm proposing would absolutely be suitable for static type-checking systems.
Also, the annotations proposal has a much tighter syntax than this metadata proposal, making the developer ergonomics more attractive for replacement of type-checking systems.
Please take a look at let me know if there's an opportunity to merge these proposals. -- https://github.com/matthew-dean/proposal-annotations
Example
Just as an example, this repo's proposal adds metadata like:
const METADATA = new WeakMap();
function meta(value) {
return (_, context) => {
METADATA.set(context.metadataKey, value);
};
}
@meta('a')
class C {
@meta('b')
m() {}
}
METADATA.get(C[Symbol.metadata]); // 'a'
METADATA.get(C.m[Symbol.metadata]); // 'b'My proposal takes the much more concise extensions on the decorators proposal and turns the above example into this form:
@'a'
class C {
@'b'
m() {}
}
C[Symbol.metadata]; // ['a']
C.m[Symbol.metadata]; // ['b']
// (note in the above that metadata is an array to allow easy "tagging"
// of multiple annotations, just like the extensions proposal)That's a reduction of ~250 characters to ~80 characters.
Where this syntax really shines is as a replacement for the controversial type-annotations proposal. Instead of adding a bunch of "ignorable" syntax to JS, it adds a single annotation syntax (@'', @[], @{}), with versatility to use strings, arrays, and objects to mean whatever a system might want it to mean.
Some examples from the proposal.
let @"string" x;
x = "hello";
let @{
name: 'string',
age: 'number'
} Person
Person[Symbol.metadata]; // { name: 'string', age: 'number' }
@'boolean'
function equals(@'number' x, @'number' y) {
return x === y;
}
@'<T>'
function foo(@'T' x) {
return x;
}This would supplant the need to add type blocks, interface blocks, generics, type assignment, type assertions, non-nullable assertions etc etc etc to the JavaScript language as "comments".
Instead, this metadata approach, because it has very little runtime effect (it does not need to execute a function to decorate with simple primitives), could supply all TypeScript / Flow requirements within JavaScript, as well as preserve those type (or whatever kind) of annotations at runtime, making writing custom runtime helpers trivial.
Thanks for considering this!