TypeScript vs JavaScript: Tug of War

TypeScript vs JavaScript: Tug of War

We all know that TypeScript and JavaScript are among the most popular and widely used programming languages in the world of application development. To understand the differences and use cases, and in order to know which one is best suited, I have done some research and have come up with logic and reasonings in the form of a blog. Here, we will be talking about the two languages, their correlation, benefits of each of them, and the primary difference.

A- Knowing TypeScript and JavaScript

JavaScript is scripting and client-side programming language which allows web pages to be interactive. This states that it runs in user’s web browser without the use of resources from the web server. It is used to perform dynamic tasks such as conducting polls and quizzes and contests. Javascript can be used with other technologies like XML, REST APIs, and more. TypeScript is a superset of JavaScript and therefore, contains all of its elements.

A1: Find the Differences

TypeScript makes JavaScript development easy since TypeScript uses all the code found in JavaScript with other coding concepts such as classes, modules, interfaces, and types.

For detailed data, TypeScript uses a concept of types and interfaces. TypeScript helps in finding errors and debugging applications. Some additional features include:

  • Generics support
  • Rest parameter feature
  • Modules support
  • Optional parameter feature
  • A compiler is used to convert to JavaScript for running on web pages, as it is a programming language

A2: Benefits of TypeScript

The advantages of TypeScript come from additional features which it offers. Here are a few great benefits of TypeScript:

1. Great to use for large coding projects

It happens that sometimes in order to improve the coding part of the project, some small and incremental changes are required to be made for the code base. These changes yield to unintended consequences. For managing such things, refactoring with TypeScript tools is a great alternative which is both, easier and faster. For understanding refactoring using TypeScript tools, you may go through the same: https://www.florian-rappl.de/News/Page/363/large-scale-refactoring-with-typescript

2. Static typing

Another great feature of TypeScript is static typing which detects bugs. As developers write the scripts and finding and fixing bugs is need of today’s DevOps team of developers, static typing helps developers in writing robust code. It also helps in maintaining it which results in better and cleaner code.

3. An amazing collaboration framework

Whenever there is a lot of coding happening by many developers in a large project, chances of messy coding and errors increase significantly. Here, Type Safety comes to rescue since it helps in detecting errors during the coding process. This makes the coding and debugging process a lot more efficient.

4. Better productivity

Clean ECMAScript 6 code, dynamic typing, and auto-completion help boost developer’s productivity and they also help the compilers in creating optimized code.

5. It is popular and in demand

JavaScript has a huge and active community of developers which makes it easier to find people who are willing to develop projects and share their expertise in coding.

6. No Annotations Required

To bring out the best from TypeScript features, developers constantly annotate their code. This makes the project less efficient.

B- Steps To Migrate To TypeScript

B1- Get Started

Check TypeScript Official Website for gearing up your project and if you are already a JavaScript developer, it is easy to grasp things.

B2- Rename Files

Ensure you rename all the ‘js’ files to ‘ts’ files. You can simply start compiling your new ‘ts’ files with TypeScript compiler as ‘TypeScript’ is just a superset of ‘JavaScript’.

B3- Fix The Compiling Errors

You may face some compile-time errors which could be because of static type checking by the compiler. Here, are few examples which can give you an idea if complaints about js code which your compiler could make:

Example One:

var xdr = window.XDomainRequest;

Solution:

// declare the specific property on our own
interface Window {
    XDomainRequest?: any;
}

“XDomainRequest” is an IE only property to send cross-domain request, it’s not declared in the “lib.d.ts” file

You will get “error TS2339: Property ‘XDomainRequest’ does not exist on type ‘Window’.”.

As a solution, you must extend the Window interface in “lib.d.ts” with an optional “XDomainRequest” property.

Example Two:

function foo(a: number, b: number) {
    return;
}

foo(1);

Solution:

// question mark the optional arg explicitly
function foo(a: number, b?: number) {
    return;
}

Args, the optional function need to be marked explicitly in typescript. If not done same it may give an “error TS2346 which states, supplied parameters do not match any signature of call target.”.

The resolution of this error is to explicitly use “?” to mark the parameter as optional.

Example Three:

var myObj = {};
myObj.name = "myObj";

Solution:

// use bracket to creat the new property
myObj['name'] = 'myObj';
// or define an interface for the myObj
interface MyObj {
    name?: string
}

var myObj: MyObj = {};
myObj.name = 'myObj';

Whenever user assigns an empty object “{}” to a variable, the typescript compiler infers the type of the variable to be the empty object without any property.

Therefore, while accessing “name”, the property gives “error TS2339 which explains that property “name” does not exist on type ‘{}’”.

By declaring an interface with an optional “name” property for it, we can resolve the error.

B4- Fix Test Cases

Once you have successfully got the JS files from those ts files, run the tests against the new JS files and fix all the failures.

You can experience the test failure while you are moving to TypeScript, you may find difference in process of exporting a function. Here is the difference found:

export function foo() {}
export var foo = function() {}

Assuming your original JavaScript code is:

var A = {
    foo: function() {},
    bar: function() {foo();}
}

The test case shows:

var origFoo = A.foo;
var fooCalled = false;
A.foo = function(){fooCalled = true;};
A.bar();
assertTrue(fooCalled);
A.foo = origFoo;

When you rewrite the TypeScript for JavaScript:

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

The test case fails. You can easily rule out the reason why it fails.

// generated from export function foo() {}
var A;
(function (A) {
    function foo() { }
    A.foo = foo;
    function bar() { foo(); }
    A.bar = bar;
})(A || (A = {}));

In the above test case, when you are replacing A.foo, you are just replacing the “foo” property of A but and not the function ‘foo’. The bar function still calls the same for function.

export var foo = function(){}

TypeScript

module A {
    export var foo = function () { };
    export var bar = function () { foo(); };
}

Generates

// generated from expot var foo = function() {}
var A;
(function (A) {
    A.foo = function () { };
    A.bar = function () { A.foo(); };
})(A || (A = {}));

Now we can replace the foo function called by A.bar.

B5- Refactor Code

The modules and classes of TypeScript help in organizing the code in a modularized and object-oriented way. All Dependencies are referenced in the file header.

///<reference path=“moduleA.ts” />
///<reference path=“moduleB.ts” />
module ADRUM.moduleC.moduleD {
    ...
}

TypeScript helps us in defining classes which is a lot more familiar to Java and C++ programmers. But you lose the flexibility which, of course, JavaScript provides.

It also allows you to define modules and classes in a quiet simpler way and generates an idiomatic JavaScript for you. Furthermore, moving test cases to TypeScript is also a great work to do, as the test cases could be auto-updated when refactoring the code in the IDE.

B6- Fixing Minification

While you are using Google Closure Compiler with advanced optimization, do not panic if the minification is broken down.

Problem 1: Exporting of Symbols in Modules

Export the symbols by the quote notation in case you want to tell the compiler not to rename the symbols in your code.

module A {
    export function fooAPI() { }
    A["fooAPI"] = fooAPI;
}

Transpiled to:

var A;
(function (A) {
    function fooAPI() { }
    A.fooAPI = fooAPI;
    A["fooAPI"] = fooAPI;
})(A || (A = {}));

As this task is a little tiresome, another option is to use the deprecated @expose annotation.

module A {
    /**
    * @expose
    */
    export function fooAPI() { }
}

Problem 2: Mistakenly removing the dead code.

The advanced optimization feature is an amazing feature which is “dead code removal” and it removes the code. This code is generally recognized as unused by the compiler.

B7- Auto-Generate Google Closure Compiler External Files

You need to declare the APIs in externs file and tell the compiler not to rename the symbols, if your js code calls external js library’s APIs, for the Closure Compiler.

Earlier one needs to be manually created by the externs files. One has to manually update its extern file, whenever one has to use a new API. Using TypeScript, you can easily find TypeScript .d.ts and the externs file have the same information.

Let us find if TypeScript compiler supports minification. Since ts compiler understands the .d.ts file, it will not need the externs files. But unfortunately, it doesn’t support it, so you may have to stay with the Google Closure Compiler.

You may also generate the externs files from the .d.ts files. This is because of open source ts compiler. You can also use it to parse the .d.ts files and convert them to externs file.
So, now when you will add a new external API declaration in .d.ts file, the API symbols will automatically appear in the externs file.

B8- Wrapping The ‘ts’ Code In One Function

‘Ts’ compiler generates code for modules like below:

// typescript
module A {
    export var a: number;
}

module A.B {
    export var b: number;
}

// transpiled to javascript
var A;
(function (A) {
    A.a;
})(A || (A = {}));

var A;
(function (A) {
    var B;
    (function (B) {
        B.b;
    })(B = A.B || (A.B = {}));
})(A || (A = {}));

A variable gets created and a function is called for each module. The function creates properties in module variable for exported symbols. You might sometimes need to wrap all the js code in a function by yourself, just like we have mentioned here.

(function(){
    if (global.ADRUM || global.ADRUM_DISABLED) {
        return;
    }

    // typescript generated javascript goes here

}(global);

C- When To Choose: Typescript vs. JavaScript

TypeScript:

  • While you decide to take new library or framework: For example, you are choosing React for new project and you are not very much known with React APIs. But you need to incorporate the same, since they offer type definitions. For navigating and discovering new interfaces you can get intellisense.
  • Compile Time Type Checking: For performing runtime type verification you can use Vanilla JS. This will increase additional runtime. This can be avoided by compile-time validation.
  • Superbly works with large projects or multiple developers: TypeScript is a great idea to use when you have large projects and you have several developers working together.

JavaScript:

  • Build Tools Required: Build tools are essential for developing JavaScript applications.
  • Strong Testing Workflow: When you possess strong JS team of developers who are proficient in implementing test-driven, then switching to TypeScript cannot be a wise deal.
  • Added Dependencies: For using libraries with TypeScript you would need their type definitions, and with every type definition, it invites an extra npm package. Also, depending on extra packages means you are accepting some risk, which is not good. Therefore, if you are not importing type definitions, you will surely lose much of TypeScript benefits.

D- The War Goes On And On:

TypeScript is becoming a great tool for organizations, especially for the ones who are busy in developing large coding projects. The structure of object-oriented programming language keeps the code simple, stable and clear to debug.

We have outlined all exciting features, both of TypeScript and JavaScript. Now the choice is all yours. Get your mobile application build today with top-notch developers at Algoworks 🙂

References: stackify, appdynamics

The following two tabs change content below.
Rachit Agarwal

Rachit Agarwal

Director and Co-Founder at Algoworks Technologies
Rachit is leading the mobility business development function, mobility strategy and consulting practice at Algoworks. He is an expert of all mobile technologies and has experience in managing teams involved in the development of custom iPhone/iPad/Android apps.
Rachit Agarwal

Latest posts by Rachit Agarwal (see all)

Rachit AgarwalTypeScript vs JavaScript: Tug of War