
\begin{DoxyItemize}
\item \href{https://rbuckton.github.io/reflect-metadata}{\texttt{ Detailed proposal}}
\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_reflect_metadata_README_autotoc_md23995}{}\doxysection{Installation}\label{md_sfcode_node_modules_reflect_metadata_README_autotoc_md23995}

\begin{DoxyCode}{0}
\DoxyCodeLine{npm install reflect-\/metadata }

\end{DoxyCode}
\hypertarget{md_sfcode_node_modules_reflect_metadata_README_autotoc_md23996}{}\doxysection{Background}\label{md_sfcode_node_modules_reflect_metadata_README_autotoc_md23996}

\begin{DoxyItemize}
\item Decorators add the ability to augment a class and its members as the class is defined, through a declarative syntax.
\item Traceur attaches annotations to a static property on the class.
\item Languages like C\# (.NET), and Java support attributes or annotations that add metadata to types, along with a reflective API for reading metadata.
\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_reflect_metadata_README_autotoc_md23997}{}\doxysection{Goals}\label{md_sfcode_node_modules_reflect_metadata_README_autotoc_md23997}

\begin{DoxyItemize}
\item A number of use cases (Composition/\+Dependency Injection, Runtime Type Assertions, Reflection/\+Mirroring, Testing) want the ability to add additional metadata to a class in a consistent manner.
\item A consistent approach is needed for various tools and libraries to be able to reason over metadata.
\item Metadata-\/producing decorators (nee. \char`\"{}\+Annotations\char`\"{}) need to be generally composable with mutating decorators.
\item Metadata should be available not only on an object but also through a Proxy, with related traps.
\item Defining new metadata-\/producing decorators should not be arduous or over-\/complex for a developer.
\item Metadata should be consistent with other language and runtime features of ECMAScript.
\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_reflect_metadata_README_autotoc_md23998}{}\doxysection{Syntax}\label{md_sfcode_node_modules_reflect_metadata_README_autotoc_md23998}

\begin{DoxyItemize}
\item Declarative definition of metadata\+: 
\begin{DoxyCode}{0}
\DoxyCodeLine{class C \{}
\DoxyCodeLine{  @Reflect.metadata(metadataKey, metadataValue)}
\DoxyCodeLine{  method() \{}
\DoxyCodeLine{  \}}
\DoxyCodeLine{\} }

\end{DoxyCode}

\item Imperative definition of metadata\+: 
\begin{DoxyCode}{0}
\DoxyCodeLine{Reflect.defineMetadata(metadataKey, metadataValue, C.prototype, "{}method"{}); }

\end{DoxyCode}

\item Imperative introspection of metadata\+: 
\begin{DoxyCode}{0}
\DoxyCodeLine{let obj = new C();}
\DoxyCodeLine{let metadataValue = Reflect.getMetadata(metadataKey, obj, "{}method"{}); }

\end{DoxyCode}

\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_reflect_metadata_README_autotoc_md23999}{}\doxysection{Semantics}\label{md_sfcode_node_modules_reflect_metadata_README_autotoc_md23999}

\begin{DoxyItemize}
\item Object has a new \mbox{[}\mbox{[}Metadata\mbox{]}\mbox{]} internal property that will contain a Map whose keys are property keys (or {\bfseries{undefined}}) and whose values are Maps of metadata keys to metadata values.
\item Object will have a number of new internal methods for \mbox{[}\mbox{[}Define\+Own\+Metadata\mbox{]}\mbox{]}, \mbox{[}\mbox{[}Get\+Own\+Metadata\mbox{]}\mbox{]}, \mbox{[}\mbox{[}Has\+Own\+Metadata\mbox{]}\mbox{]}, etc.
\begin{DoxyItemize}
\item These internal methods can be overridden by a Proxy to support additional traps.
\item These internal methods will by default call a set of abstract operations to define and read metadata.
\end{DoxyItemize}
\item The Reflect object will expose the MOP operations to allow imperative access to metadata.
\item Metadata defined on class declaration {\itshape C} is stored in {\itshape C}.\mbox{[}\mbox{[}Metadata\mbox{]}\mbox{]}, with {\bfseries{undefined}} as the key.
\item Metadata defined on static members of class declaration {\itshape C} are stored in {\itshape C}.\mbox{[}\mbox{[}Metadata\mbox{]}\mbox{]}, with the property key as the key.
\item Metadata defined on instance members of class declaration {\itshape C} are stored in {\itshape C}.prototype.\mbox{[}\mbox{[}Metadata\mbox{]}\mbox{]}, with the property key as the key.
\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_reflect_metadata_README_autotoc_md24000}{}\doxysection{API}\label{md_sfcode_node_modules_reflect_metadata_README_autotoc_md24000}

\begin{DoxyCode}{0}
\DoxyCodeLine{// define metadata on an object or property}
\DoxyCodeLine{Reflect.defineMetadata(metadataKey, metadataValue, target);}
\DoxyCodeLine{Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey);}
\DoxyCodeLine{}
\DoxyCodeLine{// check for presence of a metadata key on the prototype chain of an object or property}
\DoxyCodeLine{let result = Reflect.hasMetadata(metadataKey, target);}
\DoxyCodeLine{let result = Reflect.hasMetadata(metadataKey, target, propertyKey);}
\DoxyCodeLine{}
\DoxyCodeLine{// check for presence of an own metadata key of an object or property}
\DoxyCodeLine{let result = Reflect.hasOwnMetadata(metadataKey, target);}
\DoxyCodeLine{let result = Reflect.hasOwnMetadata(metadataKey, target, propertyKey);}
\DoxyCodeLine{}
\DoxyCodeLine{// get metadata value of a metadata key on the prototype chain of an object or property}
\DoxyCodeLine{let result = Reflect.getMetadata(metadataKey, target);}
\DoxyCodeLine{let result = Reflect.getMetadata(metadataKey, target, propertyKey);}
\DoxyCodeLine{}
\DoxyCodeLine{// get metadata value of an own metadata key of an object or property}
\DoxyCodeLine{let result = Reflect.getOwnMetadata(metadataKey, target);}
\DoxyCodeLine{let result = Reflect.getOwnMetadata(metadataKey, target, propertyKey);}
\DoxyCodeLine{}
\DoxyCodeLine{// get all metadata keys on the prototype chain of an object or property}
\DoxyCodeLine{let result = Reflect.getMetadataKeys(target);}
\DoxyCodeLine{let result = Reflect.getMetadataKeys(target, propertyKey);}
\DoxyCodeLine{}
\DoxyCodeLine{// get all own metadata keys of an object or property}
\DoxyCodeLine{let result = Reflect.getOwnMetadataKeys(target);}
\DoxyCodeLine{let result = Reflect.getOwnMetadataKeys(target, propertyKey);}
\DoxyCodeLine{}
\DoxyCodeLine{// delete metadata from an object or property}
\DoxyCodeLine{let result = Reflect.deleteMetadata(metadataKey, target);}
\DoxyCodeLine{let result = Reflect.deleteMetadata(metadataKey, target, propertyKey);}
\DoxyCodeLine{}
\DoxyCodeLine{// apply metadata via a decorator to a constructor}
\DoxyCodeLine{@Reflect.metadata(metadataKey, metadataValue)}
\DoxyCodeLine{class C \{}
\DoxyCodeLine{  // apply metadata via a decorator to a method (property)}
\DoxyCodeLine{  @Reflect.metadata(metadataKey, metadataValue)}
\DoxyCodeLine{  method() \{}
\DoxyCodeLine{  \}}
\DoxyCodeLine{\} }

\end{DoxyCode}
\hypertarget{md_sfcode_node_modules_reflect_metadata_README_autotoc_md24001}{}\doxysection{Alternatives}\label{md_sfcode_node_modules_reflect_metadata_README_autotoc_md24001}

\begin{DoxyItemize}
\item Use properties rather than a separate API.
\begin{DoxyItemize}
\item Obvious downside is that this can be a lot of code\+: 
\begin{DoxyCode}{0}
\DoxyCodeLine{function ParamTypes(...types) \{}
\DoxyCodeLine{  return (target, propertyKey) => \{}
\DoxyCodeLine{    const symParamTypes = Symbol.for("{}design:paramtypes"{});}
\DoxyCodeLine{    if (propertyKey === undefined) \{}
\DoxyCodeLine{      target[symParamTypes] = types;}
\DoxyCodeLine{    \}}
\DoxyCodeLine{    else \{}
\DoxyCodeLine{      const symProperties = Symbol.for("{}design:properties"{});}
\DoxyCodeLine{      let properties, property;}
\DoxyCodeLine{      if (Object.prototype.hasOwnProperty.call(target, symProperties)) \{}
\DoxyCodeLine{        properties = target[symProperties];}
\DoxyCodeLine{      \}}
\DoxyCodeLine{      else \{}
\DoxyCodeLine{        properties = target[symProperties] = \{\};}
\DoxyCodeLine{      \}}
\DoxyCodeLine{      if (Object.prototype.hasOwnProperty.call(properties, propertyKey)) \{}
\DoxyCodeLine{        property = properties[propertyKey];}
\DoxyCodeLine{      \}}
\DoxyCodeLine{      else \{}
\DoxyCodeLine{        property = properties[propertyKey] = \{\};}
\DoxyCodeLine{      \}}
\DoxyCodeLine{      property[symParamTypes] = types;}
\DoxyCodeLine{    \}}
\DoxyCodeLine{  \};}
\DoxyCodeLine{\} }

\end{DoxyCode}

\end{DoxyItemize}
\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_reflect_metadata_README_autotoc_md24002}{}\doxysection{Notes}\label{md_sfcode_node_modules_reflect_metadata_README_autotoc_md24002}

\begin{DoxyItemize}
\item Though it may seem counterintuitive, the methods on Reflect place the parameters for the metadata key and metadata value before the target or property key. This is due to the fact that the property key is the only optional parameter in the argument list. This also makes the methods easier to curry with Function\+::bind. This also helps reduce the overall footprint and complexity of a metadata-\/producing decorator that could target both a class or a property\+:
\end{DoxyItemize}


\begin{DoxyCode}{0}
\DoxyCodeLine{function ParamTypes(...types) \{}
\DoxyCodeLine{  // as propertyKey is effectively optional, its easier to use here}
\DoxyCodeLine{  return (target, propertyKey) => \{ Reflect.defineMetadata("{}design:paramtypes"{}, types, target, propertyKey); \}}
\DoxyCodeLine{}
\DoxyCodeLine{  // vs. having multiple overloads with the target and key in the front:}
\DoxyCodeLine{  //}
\DoxyCodeLine{  // return (target, propertyKey) => \{}
\DoxyCodeLine{  //    if (propertyKey === undefined) \{}
\DoxyCodeLine{  //      Reflect.defineMetadata(target, "{}design:paramtypes"{}, types);}
\DoxyCodeLine{  //    \}}
\DoxyCodeLine{  //    else \{}
\DoxyCodeLine{  //      Reflect.defineMetadata(target, propertyKey, "{}design:paramtypes"{}, types);}
\DoxyCodeLine{  //    \}}
\DoxyCodeLine{  // \}}
\DoxyCodeLine{  //}
\DoxyCodeLine{  // vs. having a different methods for the class or a property:}
\DoxyCodeLine{  //}
\DoxyCodeLine{  // return (target, propertyKey) => \{}
\DoxyCodeLine{  //    if (propertyKey === undefined) \{}
\DoxyCodeLine{  //      Reflect.defineMetadata(target, "{}design:paramtypes"{}, types);}
\DoxyCodeLine{  //    \}}
\DoxyCodeLine{  //    else \{}
\DoxyCodeLine{  //      Reflect.definePropertyMetadata(target, propertyKey, "{}design:paramtypes"{}, types);}
\DoxyCodeLine{  //    \}}
\DoxyCodeLine{  // \}}
\DoxyCodeLine{\} }

\end{DoxyCode}



\begin{DoxyItemize}
\item To enable experimental support for metadata decorators in your Type\+Script project, you must add {\ttfamily \char`\"{}experimental\+Decorators\char`\"{}\+: true} to your tsconfig.\+json file.
\item To enable experimental support for auto-\/generated type metadata in your Type\+Script project, you must add {\ttfamily \char`\"{}emit\+Decorator\+Metadata\char`\"{}\+: true} to your tsconfig.\+json file.
\begin{DoxyItemize}
\item Please note that auto-\/generated type metadata may have issues with circular or forward references for types.
\end{DoxyItemize}
\end{DoxyItemize}\hypertarget{md_sfcode_node_modules_reflect_metadata_README_autotoc_md24003}{}\doxysection{Issues}\label{md_sfcode_node_modules_reflect_metadata_README_autotoc_md24003}

\begin{DoxyItemize}
\item A poorly written mutating decorator for a class constructor could cause metadata to become lost if the prototype chain is not maintained. Though, not maintaining the prototype chain in a mutating decorator for a class constructor would have other negative side effects as well. @rbuckton
\begin{DoxyItemize}
\item This is mitigated if the mutating decorator returns a class expression that extends from the target, or returns a proxy for the decorator. @rbuckton
\end{DoxyItemize}
\item Metadata for a method is attached to the class (or prototype) via the property key. It would not then be available if trying to read metadata on the function of the method (e.\+g. \char`\"{}tearing-\/off\char`\"{} the method from the class). @rbuckton 
\end{DoxyItemize}