TypeScript with Ionic and Yeoman

I wanted to get TypeScript working on an Ionic project that I am starting, but couldn’t find a decent resource that helps you get TypeScript working with Yeoman generated Ionic project. So I thought i’d put down a few steps that will be useful for anyone who might need it.

Environment Requirement

This post is only going to work for you if you are using the following tools/frameworks for the given purposes.

  1. Yeoman for scaffolding and Grunt for workflow/build automation. Honestly if you haven’t heard of these or tried these, you definitely should give it a try before starting your Ionic/Angular project (or for that matter, any JS/HTML project).
  2. TypeScript as your language. There is so much hype around TypeScript and ES6 right about now. Angular 2 supposedly is going to support TypeScript strongly and if you are starting a Angular project with 1.x, you should consider going with TypeScript and structure your code in such way that it can be easily ported to Angular 2 in time to come. (Hopefully I will be writing a series of posts on this).
  3. Ionic as the mobile development framework.
  4. Angular 1.x 

This post doesn’t cover the details of setting up the above but here are a set of things you will need to install to get started.

  1. NodeJS needs to be installed along with NPM.
  2. Install Yeoman tools as per this page using NPM.
  3. Install Cordova and Ionic as per the Ionic Documentation.
  4. Install the TypeScript compiler as per this page using NPM.

Create the Ionic Project with Yo

Once you have all this in place you need to use the generator-ionic generator to bootstrap your project. So lets first install the generator using NPM.

npm install -g generator-ionic

Once you have the generator globally installed, you can bootstrap your project folder. Start by creating the project folder, navigating into it and then use the generator to create the project. There will be few steps to let you customize the project.

yo ionic [app-name]

The newly created project structure will have all the files necessary to get started with your Ionic project. You can use the Grunt CLI commands to run, emulate, test and do other things as specified in the generator-ionic page.

Include TypeScript into the Workflow

Now that we have the Ionic project structure, we need to include the TypeScript compilation step into the Grunt workflow. First you are going to need the grunt-typscript Grunt plugin to do this.

npm install grunt-typescript --save-dev

Next we need to make changes to the newly created Gruntfile.js to include and configure the typescript task. First include the plugin by placing the following line in the file. You can put this line somewhere before the grunt.registerTask  statements.

grunt.loadNpmTasks('grunt-typescript');

Once thats done we need to include the configuration for the typescript task. This needs to be added into the grunt.initConfig block.

  typescript: {
      base: {
        src: ['<%= yeoman.app %>/<%= yeoman.scripts %>/{,*/}*.ts'],
        dest: '<%= yeoman.dist %>/<%= yeoman.scripts %>/',
        options: {
          target: 'es5',
          sourceMap: true
        }
      },
      test: {
        src: ['<%= yeoman.test %>/spec/{,*/}*.ts'],
        options: {
          target: 'es5',
          sourceMap: true
        }
      }
    },

The configuration contains two parts, one for the main code and one for the test code. As you can see the yeoman.xxx (defined in the same grunt.initConfig block) is accessed to get the correct paths for the source and distribution. This configuration will compile all .ts files in the source path (in this case the app folder) and move the resulting .js and .map.js files to the distribution path (in this case the www folder). You can do similar configuration for the test code (currently compiles into the same path). All other available configuration are defined in the grunt-typscript page.

Next we need to add few more lines into the watch configuration (again in grunt.initConfig) to ensure the .ts file changes will run the typescript compiler on those files.

  watch: {
      ...
      ts: {
        files: ['<%= yeoman.app %>/<%= yeoman.scripts %>/{,*/}*.ts'],
        tasks: ['typescript']
      },
      tsTest: {
        files: ['<%= yeoman.test %>/spec/{,*/}*.ts'],
        tasks: ['typescript:test']
      },
      ...
    },

Now to the most important part – to include the typescript task into the workflow. You can simply do this by including it in the init task next to the clean step. This pretty much includes in all workflow commands defined in this particular Gruntfile.

  grunt.registerTask('init', [
    'clean',
    'typescript',
    ...
  ]);

Similarly you can include the test file compilation into the test task.

 grunt.registerTask('test', [
    ...
    'clean',
    'typescript:test',
    ...
  ]);

We are just not yet done though. In the original Gruntfile.js that was created, there is a task to copy all files from the source folder to the distribution folder. When we included the typescript task that moves the .js files, the copy task became redundant for the scripts folder. We need to fix this by excluding the scripts folder. Once you make the change your copy.app config should look like this.

  copy: {
      ...
      app: {
        expand: true,
        cwd: '<%= yeoman.app %>',
        dest: '<%= yeoman.dist %>/',
        src: [
          '**/*',
          '!**/*.(scss,sass,css)',
          '!**/*.ts',
          '!**/*.d.ts',
          '!<%= yeoman.scripts %>/**',
        ]
      },
      ...
    },

As you can see we have also made sure that no .ts or .d.ts files are copied to the distribution folder as well.

Now you can go ahead and create .ts files in your scripts folder. However to compile them successfully we need to do one more thing.

TypeScript Definitions for JS libraries

Though we are writing our new code in TypeScript, most of the framework code such as Angular and Ionic are written in JavaScript. The TypeScript compiler wont be able to recognize the symbols and resources we use which are from the JS libraries. Don’t panic – we have bunch of awesome people who have created us DefinitelyTyped just for this reason. It’s a repository of TypeScript definition files for the popular JavaScript frameworks and libraries.

We need to include the TypeScript definitions for Angular, Ionic and Cordova for us to be able to use them. We don’t want to go ahead and include all DefinitelyTyped definitions, instead they themselves provide this handy tool TSD which will let you add definitions (just like NPM or Bower packages). Are we living in an awesome time or what?!

Lets first install TSD using NPM

npm install tsd -g

Now while you are in your project folder initialize TSD in your project by issuing the following command. This will create a tsd.json file where you can save all the definitions you install for later reinstall (just like NPM).

tsd init

The tsd.json file also contains the path you want to store the definition files. I would suggest putting them into your source scripts folder to fit our above configuration. In this example we have created a folder named typings.

  "path": "app/scripts/typings",
  "bundle": "app/scripts/typings/tsd.d.ts",

Now lets install the definitions we need for the ionic project by running the following commands.

tsd install angularjs --save
tsd install cordova --save
tsd install cordova-ionic --save

Once you run these you would notice that the typings folder we created now contains all the .d.ts files. Now all you need to do is create references to these files to get your project compiled.

For this purpose you can create a _references.ts declaration source file to include all references. Something like this.

/// <reference path='typings/angularjs/angular.d.ts' />
/// <reference path='typings/jquery/jquery.d.ts' />
/// <reference path='typings/cordova/cordova.d.ts' />
/// <reference path='typings/cordova-ionic/cordova-ionic.d.ts' />

 

Hope this helped and please let me know if you find anything that I have not covered here.

Advertisements

One thought on “TypeScript with Ionic and Yeoman

Comments are closed.