Typescript is simply about programming language evololution

Typescript is not only about getting static types in javascript. It is a lang that can, and promise to, evolve, when javascript cannot because it has to support old browsers.

For wide browser support javascript is still in 1999, as vb, early php or early ruby.

Sure I could still use vb and classic asp (many do), but I don’t need to – I use c# because I think it’s better (and more fun).

Advertisements

Typescript is awesome – but still Alpha

alpha

I started using Typescript soon after the public announcement in october 2012. And I honestly thought they would have left Alpha status by now (september 2013). I’m frankly disappointed that they haven’t.

“Alpha software can be unstable and could cause crashes or data loss.” (Wikipedia)

Is the “Alpha” status as bad as it sounds? What does this actually mean?

If you check out the reported issues and the reviews you see that they still have quite a bit of work to do with the compiler before it can be regarded as completely reliable (and production ready).

Do I personally use Typescript “in production”? Yes I do, I have had js code generated by the Typescript compiler, in production since the beginning of 2013. I actually never had problems with the generated javascript. So by my experience, for the code I write, I trust the compiler to give me completely accurate javascript. Of course I had my share of compiler issues, but I was not nearly as badly bitten as others seem to have been.

Of the problems reported in Codeplex, not that many are related to the actual javascript, at least not when it comes to basic usage of the language (javascript with classes and static typing).

However – organisations who trust their compilers to “just work at all times, as with C#” should probably be careful before they start using Typescript until it reaches version 1.

It is very disappointing to hear open source library maintainers, who adopted Typescript for their library, say they strongly consider leaving Typescript because the number of problems they had with it.  In this particular case it is a very large project, written for 0.8 to begin with, and then upgraded to 0.9, where the problems begun (as far as I understood it).

Why use Typescript in the first place?

I jumped on the Typescript ship early mainly for two reasons 1) to get help dealing with the “bad parts” of javascript (as Douglas Crockford and many others talks about) and 2) to get classes and modules with a nice syntax to help structure my code.

Looking back I could have got these two things at a much lower “cost” with 1) a good habit using jslint and 2) adopting the commonly used revealing module pattern (or similar) (and getting used to a little boilerplate code).

The IDE part of the story, with solid language services inside Visual Studio, similar to C#, was only a very nice addition and nothing I looked for to begin with.

Now, lots and lots of typescript hours later, I have become so used to the intellisense and tooling help I find it hard to write javascript in an ordinary text editor anymore.

What I like about using Typescript

* Classes and modules to structure my code
* Creating more reliable javascript than I would myself
* Catching type errors
* Intellisense for my own code
* Intellisense for external libraries (with the help of community produced definition files)
* Robust code navigation
* Code documentation intellisense, using jsdoc
* Mapping js to ts for debugging within actual typescript while running the code

Laymans questions: Why Generics? And why not using C#?

When they introduced Generics in version 0.9 my first thought was – “why on earth would I want generics in javascript?” Perhaps for a version 2.0 of Typescript, but why this early?

Also – creating a compiler with such advanced features as generics must be several times more complicated to accomplish with the half finished version of the language itself. I wonder why they did not, at least to begin with, write it with C# or C++?

Summary

Typescript is simply awesome for my productivity and my ability to produce reliable, maintainable code.  I think Typescript, when it is finished, will be a great step forward for the web developer community, and in turn, for the quality and usability of the web itself.

So, it will be great – but I’m impatient. The compiler errors and the fact that the compiler is still Alpha today, 11 months after the first public announcement is surprising and a disappointment.

Update:

“Microsoft officials are saying TypeScript 1.0 will ship “later this year.””

http://www.zdnet.com/microsoft-delivers-biggest-update-to-date-to-typescript-7000016972/

I guess we just need to be patient a little while longer.

Setting up a Typescript Project Structure to make the compiler happy

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.

Learn more about underscore (and other js libs) by using Typescript

Inspired by Shawn Wildermuths recent post about using Underscore I wanted to write a short post about how using Typescript can help you learn more about that library and others.

It might sound unnessesary to use Typescript for some small simple javascript scripts for an ordinary web site, but I think the intellisense you get with it, especially with a good definition file actually can make it worth while. You will simply get help to get your jquery, underscore (or whatever library code you are using) right.

First install Typescript itself. It’s a compiler aswell as a Visual Studio plugin that adds intellisense and some nice features for managing the Typescript files to Visual Studio. Also install WebEssentials plugin to be able to handle Typescript easier outside projects made with the Typescript application project template.

Now open your web project, I just created a standard MVC4 one. And then open up the Package Manager Console.

Now check out the nuget packages matching “underscore” by typing underscore and hitting tab:

typescriptvs

Install-Package underscore.js

for the plain library. It will install itself in /scripts.

and

install-package underscore.TypeScript.DefinitelyTyped

for the Typescript definitions. It will install itself in /scripts/typings/underscore

Next, write your javascript. Err Typescript. Add a new file, select a Typescript template. Delete all sample content (don’t know why they insist having it there).

Now, add a reference to the underscore definition file, for example by dragging the file from the solution tree to the editor. Or by writing it manually:

/// <reference path="typings/underscore/underscore.d.ts" />

Now you get underscore intellisense:

typescriptvs

Cool huh? I learned much I did not know about underscore just by playing around with the code and the syntax this way.

There are typescript definition files easily available for pretty much every commonly used javascript library via Nuget from the great open source project DefinatelyTyped.

Now after adding some code, click save, and WebEssentials should run the Typescript compiler and show you the javascript:

compiled

See the difference? No, neihter do I. It’s just because Typescript allows Javascript just as is, adding type information on top. Of course you can go ahead and use classes, interfaces and even generics if you like. But that’s another story.

Note: Currently Typescript is at version 0.91, still an Alpha version. Use it at your own risk. Read the discussions and info on the codeplex site for up to date information.

Can I benefit from Grunt for my Visual Studio based web development?

Yes you can. Grunt is completely independent of IDEs and texteditors and is a really helpful tool for all kinds of web development in any editor.

Grunt is described as “a node based javascript task runner with which you can automate tasks like minification, compilation, unit testing, linting and more”. You can use it for example when you do not like to be dependent on an asp.net web server doing minification and bundling for you, or you simply like to be able to use tools that are not (yet) supported by the asp.net/Visual Studio ecosystem.

I use it when I create web applications which requires typescript compilations, css and js minifications and separate configurations for development and live deployments. Initially I used WebEssentials for that. But I found that grunt gives me more flexibility and power.

To use Grunt you only need to install Node (from nodejs.org) on your computer. With that in place you tell grunt how to perform it’s magic with the help of two configuration files:

  1. package.config (which contains the npm information about your project and its dependencies)
  2. gruntfile.js (which contains information about your build tasks)

Npm, the Node Package Manager, can help us create a package.config. Just enter npm init from your application folder:

Follow the process in a 5 minutes screen recording here.

Untitled

Answer the questions (just use the default options if you like, it’s not important now) and it will create a package.config for you.

Next we’ll open the project as a web site within Visual Studio:

Untitled

You can edit the information in the file if you like. But we’ll let the npm add some information for us automatically so please save the file before you go on to the next step.

Whenever we use an external tool to edit files for us Visual Studio will notice and ask us if we like to refresh it from file, or keep the version in the editor. I find this a bit annoying and I like it better just when Visual Studio refreshes the files completely automatic (unless I changed them of course). You can change that in the option “Auto-load changes if saved”:

Untitled

Okay. Now let’s add the grunt specific features.

First add grunt itself locally aswell as the task we will use. Go back to the command prompt and install grunt and grunt-ts for typescript compilation:

npm install grunt-ts –save-dev

Grunt-ts has grunt as a dependency so it will install that automatically. (Now dont be surprised by the loads of packages which comes with Grunt. It’s just something you need to get used to when it comes to npm packages.)

Untitled

When Npm is done installing everything you will get a command prompt like below. Also notice that package.config will got a few new lines:

"devDependencies": {
    "grunt": "~0.4.1",
    "grunt-ts": "~0.9.1"
  }

Now we need to add the Grunt Command Line Interface. We install that globally by adding -g so we can use it from any project later:

npm install grunt-cli -g

Now let’s add the gruntfile.js with everything grunt needs to perform the particular tasks for us:

module.exports = function (grunt) {
    "use strict";

    // load all grunt tasks

    grunt.initConfig({

        ts: {
            options: {                    // use to override the default options, See : http://gruntjs.com/configuring-tasks#options
                target: 'es3',            // es3 (default) / or es5
                module: 'amd',       // amd (default), commonjs
                sourcemap: true,          // true  (default) | false
                declaration: false,       // true | false  (default)
                nolib: false,             // true | false (default)
                comments: false           // true | false (default)
            },
            dev: {                          // a particular target   
                src: ["ts/*.ts"], // The source typescript files, See : http://gruntjs.com/configuring-tasks#files                
                watch: 'ts',         // If specified, configures this target to watch the specified director for ts changes and reruns itself.
                out: 'dev',
                options: {                  // override the main options, See : http://gruntjs.com/configuring-tasks#options
                    sourcemap: true
                },
            },
            live: {                          // a particular target   
                src: ["ts/**/*.ts"], // The source typescript files, See : http://gruntjs.com/configuring-tasks#files                
                watch: 'ts',         // If specified, configures this target to watch the specified director for ts changes and reruns itself.
                out: 'scripts/app.js',
                options: {                  // override the main options, See : http://gruntjs.com/configuring-tasks#options
                    sourcemap: false
                },
            },
        },
    });

    grunt.loadNpmTasks("grunt-ts");
    grunt.registerTask("default", ["ts"]);

};

It’s quite a lot of code. But mostly self explanatory. Now lets add some necessary folders:

  • ts : for the typescript code files.
  • scripts : for the compiled javascript. Bundled to one file.
  • dev : for the compiled separate javascript files. With sourcemaps.

Add a basic typescript file in the ts folder.

Now run grunt,

grunt

which will make it compile the typescript file and then keep running to watch for file changes.

Open up the compiled javascript file within Visual Studio and arrange the windows if you like to the javascript file together with the typescript file:

Untitled

Notice it re-compiles and refreshes the javascript file whenever you change the typescript file, or any other typescript file with the ts folder.

The last thing we’ll do is to stop the current grunt process (just by hitting Ctrl+C) and make grunt perform the live task instead:

grunt ts:live

See that we get the compiled file in the scripts folder instead, and without a source map.

Read more about grunt-ts and grunt.

Make grunt do more
After we compile the live version of our script we like to minify it. For that we can use the uglify plugin:

npm install grunt-contrib-uglify --save-dev

*-contrib-* is for plugins that are being maintained by the grunt core team.

Now change and add a few lines at the bottom in the gruntfile:

module.exports = function (grunt) {
    "use strict";
    grunt.initConfig({

        ts: {
            options: {                      // use to override the default options, See : http://gruntjs.com/configuring-tasks#options
                target: 'es3',              // es3 (default) / or es5
                module: 'amd',              // amd (default), commonjs
                sourcemap: true,            // true  (default) | false
                declaration: false,         // true | false  (default)
                nolib: false,               // true | false (default)
                comments: false             // true | false (default)
            },
            dev: {                          // a particular target   
                src: ["ts/**/*.ts"],           // The source typescript files, See : http://gruntjs.com/configuring-tasks#files                
                watch: 'ts',                // If specified, configures this target to watch the specified director for ts changes and reruns itself.
                out: 'dev',
                options: {                  // override the main options, See : http://gruntjs.com/configuring-tasks#options
                    sourcemap: true
                },
            },
            live: {                         // a particular target   
                src: ["ts/**/*.ts"],       // The source typescript files, See : http://gruntjs.com/configuring-tasks#files                
                out: 'scripts/app.js',
                options: {                  // override the main options, See : http://gruntjs.com/configuring-tasks#options
                    sourcemap: false
                },
            },
        },
        uglify: {
            my_target: {
                files: {
                    'scripts/app.min.js': ['scripts/app.js']
                }
            }
        }
    });

    grunt.loadNpmTasks("grunt-ts");
    grunt.loadNpmTasks('grunt-contrib-uglify'); // minifies


    grunt.registerTask("default", ["ts:live"]);
    grunt.registerTask("ts-dev", "Compile all typescript files to dev folder and watch for changes", ["ts:dev"]);
    grunt.registerTask("ts-live-uglify", "Compiles all Typescript files into one and minifies it", ["ts:live", "uglify"]);

};

Notice I have added “uglify”, a few explicit tasks, and descriptions. Now, if we like to compile the typescript for live usage and minify the js we run the command:

grunt ts-live-uglify

If we forget our task names we can list them with their descriptions by running:

grunt -help

Extra

Run MsBuild from grunt grunt-msbuild

Visual Studio addin that adds your gruntfile commands to a context menu GruntLauncher

Simple module dependencies in Typescript

I’m not that convinced about the AMD module model. I rather use a simpler model which is also easily possible to achieve with typescript: use <reference path…> and compile to one file using the –out parameter.

This is my application structure:

  • main.ts (contains bootstrap startup code, reference to refs.ts)
  • refs.ts (contains all references)
  • modules… (contains only a single ref, to refs.ts)

With this structure I run the instruction

TSC refs.ts --out refs.js

To get refs.js with all code from all referenced files. The refs.ts has all references in order (where necessary).

On deploy to the live site I simply minify the refs.js.

With this I only need to include <script src=”refs.js”> in my html.

I have the command to compile with –out as an external tool in Visual Studio. It would be nice to have it included in Web Essentials. I have disabled “create typescript on save” in my web essentials.

When I add a new module I need to remember to include it in refs.ts. After that it’s available globally in my application, and it will be included in main.js.

I also need to remember to re-build the solution (or run my custom tool) before I test run (parts of) the application after editing a file.

Execute Typescript

Want to easily execute Typescript?

Cool thing is that TSC.exe (that comes with the Typescript installation) has a -e option to execute a file. So you can simply write:

tsc -e somefile.ts

That command will compile the .ts to .js and execute that js.

But we also like to be able to see some generated output. We can do that using the IO object that TSC creates for us. So let’s write a small ts file:

declare var IO;
IO.print("hello world");

Execute that one and you get “foo” in the console. Add the TSC -e command as an external tool to your Visual Studio and you have a useful shortcut to execute whatever ts you like.

A few useful functions within IO:

IO.readFile(path:string):string;
IO.writeFile(path: string, contents: string): void;
IO.print(value:any):void;
IO.printLine(value:any):void;
IO.dir(path:string):string[];
IO.fileExists(path: string): bool;

Full IO.d.ts in this gist. (It’s auto-generated from the TypeScript source.) However – to use the d.ts (instead of the anonymous declare var IO;) you need to use a rather strange workaround currently (I expect it to be fixed soon?):

Workaround to use io.d.ts in current version of Typescript

Create an empty file to reference to (for example empty.ts). And add refs to that file aswell as to io.d.ts:

/// <reference path="empty.ts"/>
/// <reference path="io.d.ts"/>
IO.print("hello world");

Then execute it with the –out parameter:

tsc -e somefile.ts --out somefile.js