Click here to Skip to main content
15,867,686 members
Articles / Programming Languages / Typescript

Converting My Angular 1 Application to TypeScript

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
23 Mar 2016CPOL6 min read 10K   2  
How to convert Angular 1 application to TypeScript

With the soon-ish release of Angular 2, it makes sense to start upgrading Angular 1 apps to use TypeScript.

I have an Angular 1.x app called “Extreme Results”, which I want to upgrade to Angular 2 at some point. All the code mentioned in this post can be found in the GitHub repo for that app:

Typescript logo

The Angular teams upgrade guide says that one of the preparation steps for an update to Angular 2 is to migrate your app to TypeScript.

For this migration, I have focused on the build steps, not actually writing anything in TypeScript specifically. This works out because TypeScript is a super-set of JavaScript. All I really had to do for my source files was to rename them from fileName.js to fileName.ts.

The challenge in this migration was to get the build setup to compile the TypeScript files and still have everything work.

So what actually needs to still work after migration?

  • Development Environment
    • I can still start a development server which automatically compiles and gets everything ready every time I save a file.
    • No extra steps for development is crucial. It should not be more complicated to code, just because I use TypeScript!
  • Distribution Builds
    • Minification and everything compile with one simple command. It shall be no harder to create a proper build!
  • Unit Tests With Coverage
    • This turned out to be the most difficult part to get right.
    • Getting the tests to run properly was not that difficult, but coverage was not quite as easy as it required sourcemaps and an extra step before working.

Now that we know what needs to work, let's get down to business!

Turn Every File into TypeScript Files

This was the easy part. Just rename every single file from fileName.js to fileName.ts.

I will later change them to actually use TypeScript functionality. Right now, TypeScript provides no value, but more on that in a later blog post.

If you see any errors while compiling later, you can safely just ignore them for now. We will fix that another time. Right now, we will just focus on getting the build processes working with TypeScript.

If I wanted to, I could have used typescript and compiled everything manually, but I need it integrated into the build process I already have. Which brings me to the next step.

Bundles

I use something called gulp-bundle-assets to bundle all my files, which is used by the development environment and the distribution builds.

It basically bundles all JavaScript files together into smaller files (my own + 3rd party ones).

For this to work, I needed to add an extra step in the build processs to compile all my TypeScript files into JavaScript.

I used a gulp plugin called gulp-typescript.

I installed typescript and gulp-typescript with npm:

JavaScript
npm install --save-dev typescript gulp-typescript

I then added the gulp task to do the actually compilation:

JavaScript
gulp.task('typescript', ['clean'], function () {
    return gulp.src('src/app/**/*.ts')
        .pipe(typescript({
            target:'es5'
        }))
        .js
        .pipe(gulp.dest('tmp/typescript'));
    });

This compiles every .ts file into JavaScript (specifically ES5, which works on all browsers) and saves them to ‘tmp/typescript’.

And then configured the gulp task to run before the bundle task.

JavaScript
gulp.task('bundle', ['clean', 'templates', 'typescript'], function() {

I also had to update my bundle configuration file to look for my compiled files instead of the normal JavaScript files (since they no longer exist).

JavaScript
scripts: [
    './tmp/typescript/app.js',
    './tmp/typescript/**/*.module.js',
    './tmp/typescript/**/*.js'
],

This was actually everything that was required for development and distribution builds to work. The bundle task picks up all the compiled files and bundles them just like before.

If you don’t use bundles, you have to tweak this to make sense for you. Perhaps you have to point your development server to the compiled output folder, or something similar.

It should hopefully require little more effort than this, but you might have to find a solution that fits your particular build process.

Unit Tests

The first step needed for unit tests to run was to point karma.conf.js to my compiled files, instead of the regular JavaScript files (which again, don’t really exist anymore).

This also means that you have to build before running tests.

If you are using Gulp or Grunt to start your tests, then you just have to make sure you perform the TypeScript compilation before you fire up Karma.

So in karma.conf.js, all I had to do was:

JavaScript
files: [
    ...,
    'tmp/typescript/**/*.module.js',
    'tmp/typescript/**/*.js',
]

The tests now load the compiled files instead, and the tests run like they should. Huzzah!

Everything works! Except for one thing…

Coverage

I used to get a proper coverage report right of the bat from Karma. I now had to change this a little bit, since the coverage needs to be on the TypeScript files, not the compiled JavaScript files.

To do this, I needed to do several things.

Create Sourcemaps

When compiling TypeScript, you need to generate sourcemaps as well. This is fairly easy and just requires a new gulp plugin that does everything for you.

I used gulp-sourcemaps and changed the typescript task to do the following:

JavaScript
gulp.task('typescript', ['clean'], function () {
    return gulp.src('src/app/**/*.ts')
        .pipe(sourcemaps.init())
        .pipe(typescript({
            target:'es5'
        }))
        .js
        .pipe(sourcemaps.write({sourceRoot: __dirname + '/src/app'}))
        .pipe(gulp.dest('tmp/typescript'));
    });

Notice that it does a sourcemaps.init() before starting to compile the TypeScript files.

It then writes the sourcemaps to those files with a very particular sourceRoot.

The sourceRoot option in sourcemaps.write makes sure that we find the sources from where the compiled output comes from.

This is needed because I output the compiled files to a different folder (tmp/typescript) than the source files (which can be found in src/app).

Create a Coverage Report for the Tests

I will assume you have coverage reports already and have installed karma-coverage as well as configured it.

If not, take a look at my previous blog post about coverage: Add coverage to your Angular project

Before we can create a proper coverage report, we need to create one for the tests, which ran against the JavaScript files. This is done in Karma.

I still use karma-coverage to do this, but I now just use the output as a middle step to generate a proper report using the sourcemaps later.

The karma configuration file now needs these changes:

JavaScript
preprocessors: {
     'tmp/typescript/**/*.js': ['coverage']
}
JavaScript
coverageReporter: {
    type : 'json',
    subdir: '.',
    dir : 'coverage/'
}

I now run the coverage against the compiled TypeScript files (in my tmp/typescript folder) and generate a JSON coverage report for those. This report is what I’ll be using in the next step.

Create a Proper Coverage Report for the TypeScript Files using Sourcemaps

To create the proper report, I used a tool called remap-istanbul. I have not integrated this tool into any build processes other than creating an npm script for it.

The reason for this is that I don’t really need the coverage report all the time.

I create them when I need them, and more specifically, I create them in Travis (my Continuous Integration system) and send them to codecov to get a nice coverage badge in my GitHub README file.

The following npm script is all that is needed to generate a proper report:

JavaScript
"generateLcov": "remap-istanbul -b src/app/ 
-i coverage/coverage-final.json -o coverage/lcov.info -t lcovonly"

All I do is to create the coverage report is in my .travis.yml file:

JavaScript
- npm run citest
- npm run generateLcov

I could, and probably will create some HTML reports on the fly to get the most out of the coverage report:

Using the test coverage report

For more information on how to use remap-istanbul, take a look at:
https://github.com/SitePen/remap-istanbul

What Now?

Well, now I have TypeScript, but with no benefits. No real value has been added to anything just yet. So that is the next step for the app. Actually using TypeScript to get some value.

I will come back with a follow-up blog post on just that.

But at least we CAN start writing TypeScript now, without having to worry about everything breaking apart.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Norway Norway
My name is Gjermund Bjaanes. I am 25 years old, born and raised in Norway. I am a developer, geek and enthusiast in general. I’m passionate about programming and software engineering in general. Currently I focus on web development and mobile development on my free time.

I am a software engineer and developer by trade and by passion.

I have always had a very enthusiastic interest for computers, dated to when I was little. It became an obsession for programming, IT, gadgets and new technology. I love being a developer, and that is why I do it as much as I can!

Other than that; In my spare time I like to code, read, cook, hang out with friends and to work out.

Comments and Discussions

 
-- There are no messages in this forum --