TypeScript (TS) and JavaScript (JS) are two widely known languages in the development world, but what are the differences and what use cases are better suited for one over the other? In this post, we’ll compare the two languages, how they relate to one another, discuss their primary differences, and outline the benefits of each.
TypeScript is an open source syntactic superset of JavaScript that compiles to JavaScript (EcmaScript 3+). TypeScript offers type annotations which provide optional, static type checking at compile time. Since it is a superset of JavaScript, all JavaScript is syntactically valid TypeScript. However, that does not mean all JavaScript can actually be processed by the TypeScript compiler:
let a = 'a'; a = 1; // throws: error TS2322: Type '1' is not assignable to type 'string'.
TypeScript was created to “statically identify constructs that are likely to be errors”. This allows us to make safe assumptions about state during execution. Let’s compare the following JavaScript and TypeScript functions:
// Basic JavaScript function getPassword(clearTextPassword) { if(clearTextPassword) { return 'password'; } return '********'; } let password = getPassword('false'); // "password"
Nothing in JavaScript will prevent a script from calling getPassword(…) with invalid (non-boolean) parameters which will result in a silent error at runtime. This can be entirely avoided at compile time using TypeScript’s type annotations:
// Written with TypeScript function getPassword(clearTextPassword: boolean) : string { if(clearTextPassword) { return 'password'; } return '********'; } let password = getPassword('false'); // throws: error TS2345: Argument of type '"false"' is not assignable to parameter of type 'boolean'.
This contrived example demonstrates how we can prevent operations from acting on objects of an unexpected type. Historically, one of the biggest complaints of JavaScript was the difficulty in tracking down issues because of the lack of type checking combined with things like type coercion which may cause undesired results for those who aren’t familiar with JavaScript intricacies.
In addition to static type analysis, TypeScript also adds the following features to JavaScript:
Suppose the above getPassword(…) function belonged to an external library. How would I, as a consumer of that library, know the type to pass into the function? There are jsdoc comments that many IDEs and editors, such as VSCode support. Then there is the library’s own documentation, which tools like Dash make more accessible. But none of these provide the kind of experience offered by TypeScript out of the box.
Consider the fetch API as an example. The following screenshot demonstrates how we can explore the API using the VSCode Peek Definition feature. Using these tools we can quickly discover the input parameter types (RequestInfo = Request | string and RequestInit) and the return type (Promise<Response>). These kinds of tools go well beyond what is available through classic JavaScript and jsdocs.
There are many misconceptions around why someone might choose TypeScript. I’ve cherry-picked a few to discuss here.
It is common to hear developers choosing TypeScript because of features like modules and classes. However, it is important to understand these features are also available in JavaScript since ES6 and you can use Babel to transpile down to ES5 for greater browser compatibility. Because of this confusion, here is a quick syntax comparison for some of the more recent EcmaScript features. For each feature, you’ll find the TypeScript version and its compiled ES5 JavaScript along with the dynamic ES6 definition transpiled to ES5 using babel.
// -- TypeScript -- // class Article { name: string; constructor(name: string) { this.name = name; } } // -- TypeScript compiled output -- // var Article = /** @class */ (function () { function Article(name) { this.name = name; } return Article; }());
// -- JavaScript with Babel -- // class Article { constructor(name) { this.name = name; } } // -- Babel compiled output -- // "use strict"; function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Article = function Article(name) { _classCallCheck(this, Article); this.name = name; };
// -- TypeScript -- // export default class Article { } // -- TypeScript compiled output -- // define(["require", "exports"], function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Article = /** @class */ (function () { function Article() { } return Article; }()); exports.default = Article; });
// -- JavaScript with Babel -- // export default class Article { } // -- Babel compiled output -- // "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Article = function Article() { _classCallCheck(this, Article); }; exports.default = Article;
// -- TypeScript -- // function log(message: string = null) { } // -- TypeScript compiled output -- // function log(message) { if (message === void 0) { message = null; } }
// -- JavaScript with Babel -- // function Log(message = null) { } // -- Babel compiled output -- // "use strict"; function Log() { var message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; }
So you’ve decided that it’s time to introduce a type system to your front-end development workflow. Is TypeScript the only option? The short answer is no. In fact, there are two other major tools for type annotations which are worth consideration and have been discussed elsewhere.
If you need to monitor your javascript application so you can have front and back end in place, make sure you use an APM. Stackify Retrace supports javascript and can help you continuously improve your applications. Learn more about Javascript APM, better know as our Real User Monitoring.
If you would like to be a guest contributor to the Stackify blog please reach out to [email protected]