Setting up a Typescript Project Structure to make the compiler happy

Standard

While I was doing a lot of refactoring and cleaning up on a Typescript project – to be able to go further with it, and to make it work good with the newest version of the compiler – I re-thought my setup. And found a way I’m pretty happy with so far. So I’d thought I’d share it.

Disclaimer: this is an ongoing experiment, nothing to be considered as a best practice. I highly appreciate any comments.

Highly recommended read “7 Months with TypeScript” by Ted Patrick : http://tedpatrick.com/2013/06/25/7-months-with-typescript/

The project is a fairly large Single Page Application one, and it was rather cluttered when I started my refactoring. Test, experiments, dead code and the actual application code in one and the same folder structure, and one and the same Visual Studio project. (I only deployed the fresh parts though).

Be sure that you are not hit by tooling issues

If you’re having problems with Visual Studio not compiling a particular typescript file, check if all the .ts and .d.ts files have BuildAction property set to TypeScriptCompile. Seems to be a bug somewhere in the TS tooling which makes that property set to Content at rare cases. This issue.

Another VS gotcha is the ts files are being saved as ANSI which dows not work with international characters, should have encoding UTF-8 just like any other VS code file. This issue.

A third thing I bumped into on an upgraded project was I had an interface with an “export” declaration in one of my typescript files. From 0.9.1(?) that makes the compiler treat the whole file as an external module, without any further notice inside Visual Studio. So the class I had in the same file was never picked up, and did not appear in the intellisense. This is by design, but I really think VS should give me a warning about it, a TSC compile does.

Clean up the project

With the newest version of Typescript, the tooling in Visual Studio automatically references all included typescript files (d.ts and .ts, if set to TypeScriptCompile as they should be automatically). This means you should remove unused pieces of code, and unused definition files from your project, otherwise you are slowing down the compiler.

Treat the Solution as any C# one, keep separate projects for different uses

I took a step back, cleaned up the project as much as I could and realized that one way to keep the compiler happy, and my project easier to deal with – was actually to treat my solution pretty much as any C# solution. That is I now have separated projects, one for the js “assembly” and one for the actual application, and one for tests.

So this is my current solution structure (all these are Visual Studio HTML Application with Typescript projects):

  1. MyApp.Core [only typescript classes]
  2. MyApp.Core.Tests [karma based tests]
  3. MyApp.HtmlApplication [startup module and resources]
  4. MyApp.Experiments [old stuff and experiments]

Most of my coding goes into MyApp.Core obviously. There are all my classes. And as I mentioned the compiler now automatically references all typescript files, and all defintions, in the project. So I have no “reference path=” code in my files.

My assembly file

MyApp.Core compiles to a single javascript file “MyApp.Core.js” as any C# class library compiles to a single dll.

So MyApp.Core.js is the file I copy to my other projects where I need it. To get type checking and intellisense I also let the compiler to create a definition file.

I cannot (as far as I know) specify any actual order of the compiled typescript files. But, just like in C#, that does not matter as nothing is being run before I explicitly say so. I have a MyApp.Startup class with all necessary startup code. And that’s the one I instantiate from my Html application, on document ready. (Or from my tests).

A problem with this setup is as you probably note is I do not have the ts files in the running application, nor in my testproject, and because of that I get no mapped ts debugging. Currently I’m fine with debugging the js-files.

Tweak the project settings in the .csproj file

To make the compiler create a single “assembly” file + a declaration file you will need to tweak the project file slightly. 1) set the TypeScriptOutFile option to a file name, and 2) set the TypeScriptGeneratesDeclarations to true.

You do this by unloading the project, do your edits (xml) and then reload the project file. Obviously you need to be careful as the settings inside the file affect your project. However – it’s just code, and Visual Studio will inform you if you mess up. Keep a copy to be safe.

Unofficial Typescript options reference.

This is how my typescript build setup looks like: (MyApp.Core.csproj):

  <PropertyGroup Condition="'$(Configuration)' == 'Debug'">
    <TypeScriptTarget>ES3</TypeScriptTarget>
    <TypeScriptIncludeComments>true</TypeScriptIncludeComments>
    <TypeScriptSourceMap>true</TypeScriptSourceMap>
    <TypeScriptGeneratesDeclarations>true</TypeScriptGeneratesDeclarations>
    <TypeScriptModuleKind>AMD</TypeScriptModuleKind>
    <TypeScriptOutFile>myapp.core.js</TypeScriptOutFile>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)' == 'Release'">
    <TypeScriptTarget>ES3</TypeScriptTarget>
    <TypeScriptIncludeComments>false</TypeScriptIncludeComments>
    <TypeScriptSourceMap>false</TypeScriptSourceMap>
    <TypeScriptModuleKind>AMD</TypeScriptModuleKind>
    <TypeScriptOutFile>myapp.core.js</TypeScriptOutFile>
  </PropertyGroup>

unload

edit

reload

Additional build instructions to copy files automatically to the test project

I also added instructions to make it copy the created files to my tests and application projects:

xcopy /y $(ProjectDir)myapp.core.* $(ProjectDir)..\MyApp.Core.Tests\<br />
xcopy /y /s $(ProjectDir)\Application\Interfaces\.* $(ProjectDir)..\MyApp.Core.Tests\Interfaces\

The test project consists of the compiled myapp.core.js, the myapp.core.d.ts, the interfaces from the core project and the actual test files.

Still happy with Typescript

With this I’m happy with Typescript 0.9.1.1 and I see all kinds of reasons to keep using it. To be able to create javascript applications, with strong typing, and a similar syntax and structure as with C# is just so much nicer.

Sidenote, somewhat related: Classes vs Modules

I have said before that I think modules could often be used instead of classes in Typescript, as they are more light weight and they follow the style as lots of javascript libraries and samples out there.

I have changed my mind slightly about that. It is simply another style to code class free, and mixing the two can create confusion. So to keep my code clean and easy to deal with I decided to use classes only in my core project.

For the html application small startup code, and in tests, modules often makes sense tho.

About these ads

7 thoughts on “Setting up a Typescript Project Structure to make the compiler happy

  1. Jose ALfredo

    I used this configuration, but I have the problem that I can not debug in the ts files, only direct in js. I work in a large project and the single js files comes very long and difficult to manage. is it possible to debug with this configuration directly in ts files?
    Thanks

    • If you’re using 0.95 of Typescript, you can let it generate the compiled file/s to any path. Use that approach instead of build-copying. That should (I havent tested) be able to let the jsmap know where the sources are.

      • Jose ALfredo

        Thanks for your answer,

        Finally I will able to debug using the ts files with your configuration, here the details:

        I put the following tag in configuration file:

        http://localhost:37938/

        where localhost:37938 was the url in IIS express of the typescript library. This tag put the address in the source root of the mapping files.

        The problem with use the –outdir command is that all generated files are moved to other place, include the .d files. IF you have multiple libraries that can be a problem.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s