Reflection: export class metadata to JavaScript code

Topics: Language Specification
Oct 3, 2012 at 4:50 PM

It would be nice to have all the knowledge about classes/types during runtime, so that metadata driven code could work. Something like Reflection in .NET. Property and funciton metadata could be easily put on the class function as static data as an array of property/member info.

Coordinator
Oct 5, 2012 at 7:53 PM

There's an issue tracking a similar request for xmldoc/jsdoc here: http://typescript.codeplex.com/workitem/16

Is this related?

Oct 6, 2012 at 8:36 AM

Nope. That issue is about exporting metadata to another scenario of the "coding time".

This one is about exporting metadata to be used at runtime. Browsing through  the objects fields is not sufficient, as it requires an instance and above it, field values to get some info on actual metadata (names and types of the fields, names of the methods). 

example:

class abc { a: 'string' }  => 

function abc() { }

abc.members['member_a'] = { type: 'string', required: true} 

Also, some ways to have extra field attributes as in .NET would be nice to have real extendable metadata to be used by the UI.

Coordinator
Oct 8, 2012 at 11:46 PM

So far, it has been intentional that we do not preserve this type information at runtime.  It would be quite expensive in code size terms to put this all in the output, so we would likely never make it the default mode.   JavaScript also provides several forms of reflective capabilities that work rather well with code authored in TypeScript, like instanceof checks against the constructor objects that define classes.  But examples like you show are indeed information that is currently lost at runtime.  We may in the future look into an option to emit this type information, but some concrete examples of how and why you would want to leverage this might be interesting - as there may be alternative approaches to how you could approach this (for instance, using the TypeScript compiler itself at runtime).

Oct 9, 2012 at 6:54 AM

Programmers will define object hierarchies in TypeScript. Data will be passed to their programs in JSON, and stored as JSON in localStorage etc. But given that there is no type information at runtime, how will the JSON be deserialized into objects of the appropriate class, especially at deeper levels of the object hierarchy? Other JavaScript-based type systems define the types of properties in such a way as they can be inspected at runtime (for example, look at the Mongoose ORM for NodeJS / MongoDB), making automatic deserialization from the top object level down through the type hierarchy possible. The best way I can see to do this in a TypeScript system is to add an instance property to each class that is its class name (and hope no-one changes it at runtime), so that this will persist into the JSON and be a way of identifying what kind of object that data should be deserialized to. Having types that persist into the runtime class definitions would mitigate the need to do this, and make serialization and deserialization more like ActionScript > AMF, Java ISerializable etc.

Oct 9, 2012 at 10:14 AM

Personal comment: IMHO treating typeinfo as an editor time only behavior (just for intellisense) leads to a very weird situation: I can use strong type info in the editor (5% of the time) but may not let my code use this information in runtime (95% of the time). TypeScript does a huge part of the story by letting types be described --- just to let this information disappear from production code where it would provide a huge business value.

As for a very simple yet average use case, imagine a data bound editor (let's say a FormView) for an arbitrary entity type. In order to be able to implement that solely based on metadata/type information one would need the following things as an ability.

- Iterate over the fields of an instance of a class and get the field type even if the field does not have a value. This will allow for a UI that can reflect to field types and can render the correct input control (text, number, date, etc)

simbolic code example:

function displayEntityEditor( entityInstance ) {

//this is not the best way for this but what else... an instance.getType() would be nice
var type = entityInstance.prototype.constructor;

type.members.forEach( function(member) {

switch(member.type) {
   case 'string': renderTextEditor( entityInstance ); break;
   case 'date': renderDateEditor( entityInstance); break;    
}

});

}

-  Iterate over the fields of a class without an actual instance (some UI editors approache new scnearios as not data binding and editing a new instance but rahter collecting field values that makes possible to init a new entity instance).

- place and retrieve arbitrary field metadata (beyond field type) like attributes in .NET

 


Oct 9, 2012 at 10:15 AM
Edited Oct 9, 2012 at 10:20 AM
timliveshere wrote:

Programmers will define object hierarchies in TypeScript. Data will be passed to their programs in JSON, and stored as JSON in localStorage etc. But given that there is no type information at runtime, how will the JSON be deserialized into objects of the appropriate class, especially at deeper levels of the object hierarchy? Other JavaScript-based type systems define the types of properties in such a way as they can be inspected at runtime (for example, look at the Mongoose ORM for NodeJS / MongoDB), making automatic deserialization from the top object level down through the type hierarchy possible. The best way I can see to do this in a TypeScript system is to add an instance property to each class that is its class name (and hope no-one changes it at runtime), so that this will persist into the JSON and be a way of identifying what kind of object that data should be deserialized to. Having types that persist into the runtime class definitions would mitigate the need to do this, and make serialization and deserialization more like ActionScript > AMF, Java ISerializable etc.


This is absolutely a good extension of my original problem.

Similar thread: http://typescript.codeplex.com/discussions/397586

Oct 22, 2012 at 4:18 PM

Another example of where this would be useful is to provide XAML support in TypeScript.

Mar 13, 2014 at 7:20 PM
One way to implement this feature is to create a new emitter. We have the --declarations emitter. If the same information was emitted in JSON format, reflection would be solved. You do not need to pollute the emitted javascript just emit a second file that contains all public type info.

If this feature existed we could create powerful DI frameworks with typescript.
Mar 25, 2014 at 9:32 PM
There could be a compiler option if the programmer wants the metedata to be kept.
Feb 4, 2015 at 11:32 AM
Hello,

You might find this project interesting: https://github.com/artifacthealth/tsreflect-compiler.