Skip to content

Instantly share code, notes, and snippets.

@pielegacy
Created May 29, 2017 12:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pielegacy/bcc0979de980a33932030042fa3b9eed to your computer and use it in GitHub Desktop.
Save pielegacy/bcc0979de980a33932030042fa3b9eed to your computer and use it in GitHub Desktop.
Power Up your Angular 1.x projects with Typescript, An explorative report by Alex Billson

Power Up your Angular 1.x projects with Typescript

An explorative report by Alex Billson

header

AngularJs for years has provided a very solid framework for creating scalable MVC (Model View Controller) and MVVM (Model View ViewModel) applications using HTML, CSS and JavaScript.

popularity

As shown in this graph from May 2016, newer versions of the framework such as Angular 2 and Angular 4 despite being more feature-full and efficient than its predecessors have still failed to reach the same levels of popularity as the framework's original release, not even taking into account other rising framework's like Facebook's React. Due to this, Angular 1.x is still considered a very notable skill to have for front-end web dev and whilst there are many speculations as to why the framework's popularity took a nose dive in the recent years, the most notable change was Google's decision to employ TypeScript as Angular 2.0 and onwards default language.

This was seen as an odd decision by many developers however whilst the change from AngularJS 1.x to 2.0 was considered jarring by many, integrating TypeScript into the JavaScript based Angular 1.x has many benefits.

In this report we will explore what TypeScript is, what it has to offer to Angular 1.x developers and how to get started using this typed superset of JavaScript.

What you hopefully will find is that whilst it may add an additional step/s to your initial project creation, TypeScript's benefits and design will ensure your Angular project's reach their full potential and remain solid for years to come.

What is TypeScript?

typescript features

Described as "JavaScript that scales" TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. A Microsoft product, TypeScript was created by Anders Hejlsberg and his team at Microsoft in an effort to provide the same feeling of type safe programming but in a web development environment. Due to the fact that at heart, TypeScript is just JavaScript, it has gained a lot of traction in the web dev community.

TypeScript has a tonne of features but the most notable of them (as is implied by the name) is the type system built into the language. Type declarations in the language are as apparent as you wish them to be. A variable's type can be defined explicitly or be gained implicitly through the typescript compiler.

Using a simple syntax of:

var identifier: datatype = value;

you can declare a typed variable in TypeScript, the TypeScript compiler (tsc) ensuring that upon compilation this variable is type safe.

If this type declaration isn't followed, an error is thrown as expected from any other typed language. This can be integrated into text editors that have TypeScript support such as Sublime and VS Code; an example from the latter looking like so:

typescript error

For some, this will be the extent to which they use the power of TypeScript but upon further inspection most will realise the language offers much more than typechecking.

As TypeScript is a transpiled language, it has support to target a certain version of JavaScript and use a process known as a "polyfilling" to allow newer features of JavaScript to be compatible with older browsers. A simple example of this is the ES2015 arrow function. The arrow function is a newer feature of JavaScript and is very powerful as it allows for cleaner function declarations using var, let and const as well as single line functions.

This is very powerful and aligns with the very event driven, closure emphasised design of the language. Say we were to write up a simple arrow function in TypeScript called greet which greeted the user it would look like so:

const greet = (name: string) => console.log(`Hello ${name}`);

We see here there are multiple ES2015+ features including:

  • Arrow functions
  • The const keyword
  • String literals

Running this through Typescript (in this case the online TypeScript Playground) we see the output is compatible with older versions of the language:

transpiled greet

These are just a couple of features of TypeScript, their usefulness in Angular 1.x projects apparent through application.

Enter Angular 2.0

The developers at Angular were convinced that TypeScript was the future of JavaScript development, thus the choice to write Angular 2 and onwards in the language.

Despite this seeming like a very large change to take into account for Angular developers, in comparison to the fundamental changes made to Angular with the creation of Angular 2 TypeScript is the least of an Angular 1.x developer's problems.

The foundations of Angular 1.x were simple; create a front end framework for MVC, MVW and MVVM development using JavaScript. Technologies such as Ruby on Rails and ASP.NET MVC had long provided backend developers with the means of developing MVC applications using traditional serverside architecture, however as time goes on the need the for Single Page Applications (SPAs) grew greater and so Angular 1.x for the most part filled this void.

Defining a view was done using HTML files and snippets, powered by Angular's directives (often prefixed with the characters "ng-") developers were able to build dynamic views using the same HTML they had been using already.

Using Angular 1.x's $scope object, developers were able to define global values, functions and other objects that could be reflected throughout the application; always up to date.

If a value was defined with scope such as a name:

$scope.name = "Alex Billson";

it could be referenced in an HTML view using Angular's handlebars operators:

<p>{{name}}</p>

the output of course being:

<p>Alex Billson</p>

From this $scope object, it is a given that we would use the scope to define the model in our MVC/MVVM application. This model being worked with in our application's controllers.

The controller of an Angular project is defined using the controller module. Assuming an Angular application has been defined as a variable called app;

var app = angular.module("app", []);

a controller can be created using app;

app.controller("exampleCtrl", function($scope){
    // Controller code here
});

There you have it; the M, the V and the C/VM of our application. The reason I talk about all of this is to give some context as to what made the change from Angular 1 to Angular 2 so drastic.

With the release of Angular 2, the MVC aspects of Angular 1 are very much obfuscated in favour of progressive web apps using components.

This is very much more of the likes of React and Vue (competing frameworks) but in comparison to Angular 1.x it might as well be an entirely new framework. In fact Angular 2 is an entirely new framework, it is not an upgrade of 1.x; it is a rewrite.

According to a Quora answer from Er Shahbaz Sharif there are also major changes to the entire philosophy of the framework.

Taken from Quora

To start, template directives and controllers no longer exist; they have been replaced by components. This can be incredibly confusing components have a syntax that lacks any major resemblance to the creation of an Angular 1.x controller.

The $scope variable is gone, in its entirety. This means there is no longer an easy, global object to store the application's data. The updating and watching of variables is now handled implicitly by components which whilst sounding easier removes the ease of use that came with $scope. Another problem with removing $scope is the traditional way of maintaining models in an Angular application is gone as well.

There are other minor changes such as the renaming of directives and their usage, ng-model no longer a "two-way data binding" as it used to be and even local variables requiring a # prefix when being used in directives but its clear the biggest changes came in the removal of controllers and $scope.

Personally, I feel this is the biggest issue with the move from Angular 1 to 2; not the usage of TypeScript. Whilst TypeScript tries to make itself easy to understand for existing JavaScript developers; Angular 2.0 does not give off this same attitude for Angular 1.x developers.

Despite Angular 2.0 having such links to TypeScript however, there is still a lot of benefits to using TypeScript with Angular 1.x; especially to enforce that Model-View-Controller/ViewModel architecture that is very much prevalent in the framework.

Setting Up

TypeScript typings

One major feature of TypeScript is the tooling support it gives. TypeScript's type system allows for the easy documentation of libraries, especially from a code completion perspective.

Similar to the meta-data provided with .NET Dynamic-Link Libraries (DLLs) TypeScript's Type Definition files (.d.ts files) provide interface and class data which can be used by text editors, IDEs and the TypeScript Compiler tsc to ensure the type safety and validity of your code.

Whilst TypeScript will provide this logic for the standard JavaScript library by default, when working with frameworks such as Angular it is necessary to find the .d.ts files for Angular so that you as a developer can fully benefit from TypeScript.

Using a repository such as Definitely Typed or Typings makes this very easy, including the file in your working directory all that is needed.

/// <reference path="../../typings/modules/angular/index.d.ts" />

// app can be used application wide to define Angular related code
var app = angular.module("testApp", []);

This typings file can be referenced using the triple slash reference, this only needs to be done once in your .ts files and once included editors that have support for TypeScript will be able to provide code completion for it;

type definitions example

Now that we're all set up, lets get into how we can use TypeScript for better MVC development;

Truly Modelled Models

In most MVC frameworks, the Model represents the data of the application. In a school application, your models would include data such as students, classes, rooms and teachers.

This lends itself well to object oriented development, in the case of ASP.NET MVC for example defining a simple student with a name, age and ID number would be as easy as;

public class Student
{
    public int ID { get; set; }
    public string Name { get; set; }
    public int Age  { get; set; }
}

In the case of JavaScript, this isn't really possible. JavaScript is very much a dynamically typed language and whilst this can mean a more lenient, easier to work with language it can be a real pain to debug and ensure the validity of.

When working with a model, we don't want unsurety. Models in application design are supposed to be lean and easy to understand, often not requiring any code to be written except for that of the data members.

Previously with Angular we could define a model using a typical JavaScript object and the $scope.

Creating a Student named Alex Billson, who is 20 years old and has an ID of 101091995 would look like;

$scope.student.id = 101091995;
$scope.student.name = "Alex Billson";
$scope.student.age = 20;

Simple, but poses some problems;

  • How do we know that ID, Name and Age have values?
  • How do we know that student itself has been defined?
    • Referencing $scope.student.name for example is possible even if $scope.student is undefined
  • How do we know that the data types are correct?
    • $scope.student.id = "101091995"; isn't the same as $scope.student.name = 10191995; despite JavaScripts incredibly weak type system

In AngularJS applications, modelling our data is such a large part of developing safe web apps and this is where TypeScript's type system helps us achieve this.

Take the previous student problem, some safety could be gained through the usage of an interface;

interface Student
{
    id: number;
    name: string;
    age: number
}

Interfaces, as with most other programming languages, provide a set of a data that needs to be abided to in order to identify as a certain type. Using this new Student interface we could approach the previous scope declaration like so;

var student: Student = {
    id: 101091995,
    name: "Alex Billson",
    age: 20
};

$scope.student = student;

Through the definition of a Student interface, we have overcome the problems previously faced using vanilla JavaScript.

We know that our student model will need to have 3 things, an id, a name and an age. If one is detected as missing, TypeScript will throw an error and not compile to JS;

interface error

Such a simple implementation as this Student will make developing large applications with Angular 1.x so much easier. Editors with TypeScript support will provide code completion for this interface, meaning that assuming the Student type has been assigned you will only be able to reference members of student and nothing else;

student example

The only drawback of Angular 1.x when working with interfaces is that anything assigned to the $scope object will be treated as an any datatype; as if it was a normal JavaScript variable with no set types.

This can be overcome thanks to TypeScripts explicit typecasting system; using the as keyword <datatype> operator you can cast any data type as another data type;

($scope.student as Student)
// or
(<Student>$scope.student)

and access its members with the same features as if they were defined as such;

intellisense

This means that assuming you want to treat your TypeScript as a statically typed language, you can do so and if you feel at some points its not necessary; you can ignore the paradigm and work with your code as if it was vanilla JavaScript.

This impression of models with set data types however is sure to make development easier with your Angular 1.x projects and is just one of the many features TypeScript offers the framework.

Easy to Understand Angular

Working with the many modules for Angular such as the routing and HTTP module is easier thanks the typed definitions you are able to download. A simple search using typings will find that the keyword angular allows for 93 possible type definitions packages;

typings search

The level of code completion and hinting that comes with these definitions would often equate to hours of looking at AngularJS documentation; not to mention the piece of mind that comes with the type system.

Support and Simplicity

JavaScript as a language has had a huge facelift in the past couple of years thanks to the development of ES2015 and later versions.

As mentioned, TypeScript supports the newest JavaScript features out of the box and will polyfill new features to support older browsers. Angular being a framework that will run on older browsers such as Internet Explorer 11, will benefit from this transpilation and you as a developer will also benefit from the little things ES2015+ has to offer.

Rather than filling up a list using a generic for loop, ES2015+ will allow for the usage of iterators and the for .. of loop;

$scope.items = [];
for (let item of someCollection)
    $scope.items.push(item);

Writing up closures is much easier thanks to the arrow functions, especially when there is no need to use the function or return keyword;

$scope.square = (x:Number) => x * x;

On top of this, there is no need to treat it any differently in your Angular views;

<p>{{square(2)}}</p>

Being able to write up Object Oriented JavaScript without using the clunky prototype syntax is another benefit, especially when its guaranteed to work on the older supported browsers.

Thanks to TypeScript, your Angular code will not only be easier to read and write but will also have the same functionality no matter the browser.

Structured Projects

Angular is designed to support large SPA applications, however with many JavaScript files requires a lot of effort.

Whilst there are tools such as Grunt and WebPack which will package JavaScript code and condense it in the process, TypeScript is able to emulate this functionality to an extent using the --outFile option when compiling or the outFile attribute of the TypeScript config file (tsconfig.json).

outfile

In this example, see that outFile is set to js/index.js which means that all transpiled TypeScript will be collated into a single JS file.

Whilst this isn't much, it helps to enforce a structured MVC project even from something as simple as the directory. Taking one of my Angular projects using TypeScript for example, I try to enforce a good directory structure so that files are easily accessible depending on their purpose.

structure

Whilst its possibly all just for aesthetic reasons, working with this larger project is made much easier thanks to this system and it's because of TypeScript I am able to integrate it into my general development.

Angular 1.x is a powerful web framework that whilst having many good values and solid foundation to be built off, has been somewhat neglected in the design of its newer iterations.

Through the usage of TypeScript's powerful typing, polyfill and outfile systems; using Angular 1 is a much more enjoyable and solid experience.


Referenced Resources

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment