DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. JavaScript
  4. The Benefits of Migrating From JavaScript to TypeScript

The Benefits of Migrating From JavaScript to TypeScript

Making the jump from JavaScript to TypeScript has a lot of pros. Learn about class and module support, static typing, and JavScript packaging.

Raphael Feng user avatar by
Raphael Feng
·
Oct. 22, 15 · Analysis
Like (5)
Save
Tweet
Share
5.28K Views

Join the DZone community and get the full member experience.

Join For Free

Recently, we moved our Browser RUM agent from JavaScript to TypeScript. In my last post, I focused on walking through the steps of migrating from JavaScript, the challenges, and best practices we uncovered along the way. This one will focus on more details of the benefits and one suggested features we found.

TypeScript’s Main Benefits:

  1. Class and Module support
  2. Static Typing (Static type checks to surface more bugs at compiling time )
  3. ES6 features support
  4. Clear Library API Definition
  5. Build-in Support for JavaScript Packaging
  6. Syntax Similarity to our backend languages (Java, Scala)
  7. Superset of JavaScript , easier to learn for JavaScript developers compared to CoffeeScript or ClojureScript

Class and Module Support

Key words like class, interface, extends and module are available in TypeScript.

You can define a class as below:

// class define in TypeScript
class VirtualPageTracker extends Tracker {
private virtualPageName: string = ‘’;
constructor(name) {
super(name);
}

getName(): void {
return this.virtualPageName;
}

static getTrackerName(): string {
return “VirtualPageTracker”
}
}     

 TypeScript compiler will transcompile it to:

// Transcompiled JavaScript

var __extends = (this && this.__extends) || function (d, b) {

   for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];

   function __() { this.constructor = d; }

   d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());

};

var VirtualPageTracker = (function (_super) {

 __extends(VirtualPageTracker, _super);

   function VirtualPageTracker(name) {

       _super.call(this, name);

       this.virtualPageName = ;

   }

   ;

   VirtualPageTracker.prototype.getName = function () {

       return this.virtualPageName;

   };

   VirtualPageTracker.getTrackerName = function () {

       return ;

       VirtualPageTracker;

   };

   return VirtualPageTracker;

})(Tracker);

Static Typing

var name: string;

name = 2; // type error

function foo(value: number) {}

foo(''); // type error


interface Bar {

    setName: (name: string) => void;

getName: () => string;

}

Here is a practical example. If we use the wrong data type in the browser beacon, we get compiling errors. Before using TypeScript, they could only be found by testing against back-end.

var bar: Bar = {

getName: function() {return 'myName';}

} // type error, setName function is missing in the object assigned to bar.      

ECMAScript 6 Feature Support

ECMAScript 6 is the current version of the ECMAScript Language Specification with more language features. With TypeScript, you can start using many ES6 features although it may not be supported in your target browser. TypeScript can be compiled down to different javascript standards like ES3, ES5, or ES6. Some of the features come in handy, such as the following. 

You can write: 

// for..of loops
var arr = ['a', 'b', 'c'];
for (let item of arr) {
   console.log(item);
}      

It’s compiled to: 

// compiled JavaScript

var arr = ['a', 'b', 'c'];

for (var _i = 0; _i < arr.length; _i++) {

   var item = arr[_i];

   console.log(item);

}      

Refer to TypeScript ES6 Compatibility Table for more ES6 features you can use.

Clear API Definition

To let other TypeScript libraries access your library, you need to create a .d.ts file to declare all your public APIs of your library with the typing information. This enforces each library you are developing to have a clearly defined API. We found it to be a good way to track and maintain our APIs.

Build-in Support for JavaScript Packaging

You can define one main entry .ts file listing all the ts files in it. Running the TypeScript compiler with the –out option, the compiler will concatenate all the listed files and the referred files (directly or indirectly) into one js file in the referring order.

Now we can easily tailor our library into multiple versions. For example, the same code base can generate specific versions of browser agents for desktop browser and mobile browser with specific features for different devices. We just need to create one main entry file for each version with the module files listed in it. In addition to this benefit, we also found some missing features that could potentially be implemented; one being to merge the same module into the same function rather than multiple functions.

module A {
   function foo() { }
}

module A {
   function bar() {
       foo();
   }
}      

This generates the code below with compiling error “cannot find name ‘foo’”:

var A;
(function (A) {
   function foo() { }
})(A || (A = {}));
var A;
(function (A) {
   function bar() {
       foo();
   }
})(A || (A = {}));      

The foo function is defined within the first anonymous function call for module A is not visible in the second anonymous function call, so it has to be exported as:

module A {
   export function foo() { }
}

module A {
   function bar() {
       foo();
   }
}      

This generates the code below without error:

var A;
(function (A) {
   function foo() { }
   A.foo = foo;
})(A || (A = {}));
var A;
(function (A) {
   function bar() {
       A.foo();
   }
})(A || (A = {}));      

The issue here is now A.foo is not only visible to module A–anyone can call it and modify it now. There is no visible module-level concept which should be similar to Java’s “package-private” when there is no modifier for Java classes or members.

This could be solved by generating:

module A {
   export function foo() { }
}

module A {
   function bar() {
       foo();
   }
}      

to:

var A;
(function (A) {
   function foo() { }

   function bar() {
       foo();
   }
})(A || (A = {}));      

The problem of merging into one function is a potential name conflict between the same module in two files. The compiler can report error in this case, and if two people are working independently on the same module in two files, it would be better to create two different sub modules. Merging this into one function could be a feasible way support module-level visibility.

As I write this article, I notice the /* @internal */ annotation in the ts compiler source code; it’s an experimental option released with typescript 1.5.0-alpha to strip the declarations marked as @internal. It helps to only include the declarations without @internal (which serves your external APIs) when generating the .d.ts file from your code. And if your end users are using TypeScript too, this prevents them from accessing your internal members.

Generating the .d.ts file for:

module A {
   /* @internal */ export function internal() {}
   export function external() {}
}      

by:

tsc -d --stripInternal A.ts     

will output:

declare module A {
   function external(): void;
}      

However, if your end user still uses JavaScript, they can still use the internal function.

Conclusion

By and large, it’s a pleasant and rewarding experience to move to TypeScript. Though it adds limitations on your JavaScript implementation, you can either find a good workaround or implement the benefits that outweigh it. Moreover, it’s an active open source project (about 200 commits to master in last month) with useful and substantial documentation to help you start easily. And just in March this year, Google also announced they would replace AtScript with TypeScript. Angular 2 is now built with TypeScript too. So far, the move to TypeScript has proved beneficial.

TypeScript JavaScript

Published at DZone with permission of Raphael Feng, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Java REST API Frameworks
  • Building a REST API With AWS Gateway and Python
  • gRPC on the Client Side
  • Getting a Private SSL Certificate Free of Cost

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: