Update 19/07/13 - oh, too many things to do, not enough time to do them. Given how far TypeScript has moved on since I wrote the first spike of this, it needs a complete overhaul. Which I don't have time to do now. I hope to get around to it later in the year.

Update 11/04/13 - the project is not dead, honest! I haven't had time to work on this for a while, but hopefully a 2nd release coming soon which will patch most of the holes remaining in the feature set and make the tool properly useful. I'm also looking at integration with the latest VS2012 release and in particular the knockout.js stuff. Watch this space.


Project Description
A simple tool to export .NET types into TypeScript for client/server bridges etc. Uses reflection so can be used with any .NET language (with many limitations).

Details
tsexport is a simple command-line tool. Point it at one or more .NET assemblies, and specify which types to export (or just allow it to export all the public types it can find) and it will generate a valid TypeScript file representing the public fields, properties and methods of the exported types which can be used in your TypeScript projects. This is particularly useful if you're moving domain objects or entities from server to client and back again, for example using knockout.js.

A few quick notes:
  • First, and most importantly - this tool is not intended to produce production-ready code you can just use. It gets you a head start versus having to re-type everything when you're making TypeScript versions of existing .NET types. You will need to do plenty of work to get truly viable and optimal TypeScript. Bear in mind that TypeScript itself is a rapidly-developing language that's not finished yet. To turn the output of this tool into TypeScript that compiles is one thing - to create idiomatically correct and useful TypeScript is quite another. Don't confuse the two.
  • The exporter uses reflection to find type and member information. The .NET Framework must be able to load all the assemblies you specify, which means any assemblies that they depend on must either be in the same folder or installed in the GAC. You can't export an assembly for which you don't have all the dependencies available.
  • As of right now, the exporter doesn't do inheritance, ie it will export types that have an inheritance relationship but it will not mark that relationship with the extends keyword. I'm working on this and it should be available soon. Note that only properties and methods defined in the type are exported - properties / methods inherited from a parent class are not. I'm working on a solution that doesn't go all the way down to object such that every single exported type has GetHashCode etc.
  • The exporter will only export public classes and interfaces. This is an artificial limitation, so if it's really important to you, just change the code :-)
  • The exporter will export generic types (including generic type definitions), but it strips them of their type parameters. This may make them useless, but I figured it was better to export them than to ignore them.
  • A fairly liberal approach is taken with type conversion - anything vaguely numeric in .NET becomes a number in TypeScript. Except enums, which become string values. Guids and DateTimes become strings too.
  • The exporter will try hard to resolve the type of a property or method, but it must either be a standard .NET primitive type (and not all of those are catered for), or a type the exporter 'knows' - ie one that's on the list to be exported. Otherwise it will leave the property untyped or the method without a return type.
  • Nullable types are unwrapped - ie int? becomes number in TypeScript, since null is always an acceptable value for a JS variable.
  • Any type that implements IEnumerable<T> is exported as an array. Types implementing just IEnumerable (other than arrays) are left unspecified. Not sure how you indicate object[] in TypeScript.
  • Overloads - in TypeScript you don't have overloads in the sense you'd have them in .NET. If the exporter finds an overloaded property or method name, it marks each overload after the first with _overload_n where n is the index of the overload. This could really be done better (perhaps with signature merging?) but for now, you at least know where your overloads are and can choose to merge / edit / remove them as necessary.
  • Indexers / parameterised properties - in C# the indexer is syntactic sugar over a parameterised property called Item. The exporter just treats these like properties and drops the index parameters, which is almost certainly not what you want to do. Since this would be represented by a method in TS/JS, really we should either convert to methods or ignore them. One for a point release, perhaps. Overloaded indexers, BTW, are treated like any other overload.
License etc
This code is licensed under GPLv2, primarily because I'm using some other code that's GPLv2 in it; otherwise I'd have made it BSD or public domain.

I've put it up here primarily to make it available to anyone who might find it useful. I do not intend to maintain it, take patches etc. It's not a 'project'. Feel free to grab it if you think it might be useful to you. Just remember if you alter it and distribute those alterations, GPL kicks in.

Last edited Jul 19, 2013 at 10:31 AM by neilhewitt, version 17