Trying out TypeScript — Part 1

Justin Krup
priceline labs
Published in
5 min readJul 10, 2019
TypeScript (left) vs JavaScript (right)

At Priceline we’re maintaining thousands of lines of codes for the front-end, across several dozen repositories. Because of this, it’s important that any major undertaking, such as using TypeScript, has a clear path to not being disruptive.

Why use TypeScript?

Much Better Development Experience

By using TypeScript we can get powerful intelligent autocompletion.

By defining our object types we get intelligent autocompletion on our objects.

Easier to Identify Bugs

Airbnb famously claimed that 38% of bugs were preventable with TypeScript

Airbnb recently stated that 38% of bugs were preventable with TypeScript.

For example, when converting one file to TypeScript, we got an error message on a line of code that looked like this:

someArry.sort((a, b) => a > b)

The issue is Array.prototype.sort should be given a function that returns a number, not a boolean, and thus will not be sorted properly in many cases. Since JavaScript is not strongly typed, it treats false as a 0 and true as a 1, so no error is even thrown, but buggy sorting logic can persist in the application.

Hesitations against using TS

So given these great reasons to use TS, why isn’t everyone already on it?

Well, there are a few reasons:

Cost of Updating Build Pipelines

There is some amount of overhead involved in the build process. Almost every application these days already has a build pipeline, but if you were working without one (i.e. writing vanilla JS that runs directly in the browser or via node) then you’d need to start using build tools. Even if you already have a build pipeline, you would need to reconfigure it, which can sometimes mean a day or two of chasing down weird issues.

New Language, New Syntax

It’s a “new” language to learn. If you’re not used to it, the syntax can certainly be off-putting. Seeing interface HydratedWindow extends window { ... } or function (user : User, action : ActionEnum) can be a bit off putting for some developers who are not familiar with it. In particular, programmers with little experience using strongly typed languages will struggle with this syntax.

Both of these concerns are addressed below.

How We Started Using TypeScript

At Priceline, we went about introducing TypeScript through a very cautious approach. We actually began not by using TypeScript directly, but rather by getting many of the benefits of its language-server via comments in JavaScript.

Benefitting from TypeScript by Just Adding Comments

The TypeScript Compiler tsc and typescript-language-server can actually read JavaScript and JSDoc comments to provide all of the benefits of TypeScript! There’s a great article here that covers this at length, but essentially you can just write comments following a particular syntax around your existing JS code and set a //@ts-check at the very top of your file and in VSCode (or any editor that can integrate with the typescript-language-server) you’ll see typechecking, autocompletion, linting, etc.

A vanilla JavaScript file with JSDoc syntax, providing strict typing linter errors in Vim.

By following this methodology, there is no additional compile step, since all that is actually being added is comments. Thus we could keep our existing build process completely untouched.

This has the added benefit of encouraging people to start writing documentation. Since you’re already adding all of these multi-block comments, it’s easy to start including things like descriptions rather than just types.

Our Approach

As we worked on existing tasks, we would occasionally drop in a few JSDoc code blocks to get types just for those functions, and just “type” as we go, rather than halting our work to expend effort to fully re-write an entire repo. Some tricks we used would be to temporarily turn on strict: true in our linter’s settings to see anywhere we are using an implicit any type and then resolve those within a single file.

Important to recommend that you not bite off more than you can chew. In our GraphQL projects, we’re often dealing with very large nested Objects. We don’t want to just use type Object as that’s hardly any better than any, but on the other hand it can take hours to fully type out these objects. So we’ve decided to often follow JS’s pattern of “shallow copying”.

If we’re working with some massive object we’ll usually just declare the top level shape of it, and any children we are using, but just use Object type for anything lower level. For example:

/**
* @typedef {Object} APIResponse
* @property {Object} details
* @property {string} statusCode
*/

Rather than going into all the details of the details object right away, on our first pass we’re simply working on getting all the highest level objects defined.

Moving to Full-Blown TypeScript

Once we got a taste of some of the benefits of TypeScript by using JSDocs, we felt ready to bite the bullet and try out full-blown TypeScript. Since we were already using Babel, the build system configurations were fairly easy. We just had to upgrade to Babel 7, and then it was straightforward to just use the babel-preset-typescript plugin, and tell Webpack to include .ts files.

Since Typescript is a superset of JavaScript, whenever we feel like adding some types, we can just rename an existing .js file to .ts and begin to add typing.

Conclusion

We’re really just getting started with using TypeScript here, but Priceline is excited for what TypeScript has to offer for our engineering process and we look forward to sharing more in the future.

If you’ve been hearing about TypeScript and are unsure of how to start benefiting from it, hopefully this has provided some insight on how you could apply it either in your existing applications, or in your next one.

Excited by what we’re doing at Priceline? We’d love to have you apply here.

--

--

Justin Krup
priceline labs

Full-Stack Web • Deployments • Docker • Unity3D • Entrepreneur • 中文 • 日本語