DEV Community

Jeremy Likness ⚡️ for Microsoft Azure

Posted on • Originally published at blog.jeremylikness.com on

TypeScript for JavaScript Developers by Refactoring Part 1 of 2

Learn TypeScript by taking an existing JavaScript application and migrating it to TypeScript.

I created a repository with the goal of teaching TypeScript to JavaScript developers. Imagine if you could use a tool that finds defects for you automatically and makes it easier to squash bugs before they make it to production! This walk through demonstrates how.

JeremyLikness / TypeScript-from-JavaScript

Learn TypeScript through a series of refactorings to existing JavaScript code.

TypeScript from JavaScript

This is a project you can walk through commit-by-commit to see the transformation of JavaScript code to TypeScript.

@JeremyLikness

Background notes:

  • 1995: Mocha becomes LiveScript, written in 10 days
  • 1996: JavaScript lives!
  • 1997: ECMAScript 1 sets standards
  • 1999: ECMAScript 3
  • 2005: jQuery "Normalize the DOM"
  • 2009: Node.js, ECMAScript 5
  • 2012: TypeScript (and there was much rejoicing)
  • 2015: ECMAScript 2015 ("Harmony")

Intro

git checkout d65aed6

Currently, there is a small JavaScript "app" that you can run with the command:

node index.js

There are some defects and if you browse to JavaScript in your IDE, you may or may not get appropriate hints about what's wrong.

Transform to TypeScript

git checkout 08f09e3

JavaScript is valid TypeScript (with a few exceptions) so we'll start by setting up TypeScript.

npm install --save-dev typescript

Add two build scripts to the package.json file for compiling and compiling on a watch:

"scripts"

The repository contains documentation paired with several commits to walk through the process. If you’re a hands-on person and want to dive in, visit the repository and get started right now! I recorded a companion video series to guide you through each step.

TypeScript logo

TypeScript

Each video is only a few minutes long so feel free to bookmark this page and come back often. You may have already found these videos from my Twitter thread.

1. Introduction

In this step I introduce a simple JavaScript app that doesn’t behave properly when run with Node.js. I begin the migration to TypeScript by adding the TypeScript compiler, initializing its configuration, and renaming the index.js file to index.ts.

Note: an alternative way to initialize TypeScript’s configuration file is to use the npx command, like this: npx tsc --init

2. Configuration and the Spread (Rest) Operator

The TypeScript configuration is updated to turn off the requirement for strict typing. This removes all errors but one. The error happens to be a bug that was discovered by TypeScript. To fix the defect, a “spread operator” is used to allow a list of parameters to be passed in and parsed as an array. Because the older version of JavaScript doesn’t support the spread operator, TypeScript automatically generates the compatible code. This fix improves the application, but a few defects remain.

🔗 Learn more about the tsconfig.json file

🔗 Learn more about “rest parameters”

3. Classes and Types

A major benefit of using TypeScript, as you may be able to guess from the name, is the ability to use classes and types. I refactor the code to use classes instead of function constructors and annotate the properties with types. This immediately uncovers another bug for us that will be easy to fix in the next step.

🔗 Learn more about basic types

🔗 Learn more about classes

4. Custom Types

The class refactoring revealed a property that wasn’t named consistently. This is fixed by updating the constructor function to match the names use in other code. Next, a custom type is defined that declares the two possible string values for contactType: mobile and home. This reveals a defect that, when fixed, corrects the phone display logic.

🔗 Learn more about custom types

5. Scope and the “let” Keyword

A bug has surfaced due to the way variables are captured in scope in JavaScript. Rather than wrap the call with additional code that adds complexity, a simple change is to specify the variable with let. The TypeScript compiler then knows to manage scope for older versions of JavaScript and passes through to modern implementations.

🔗 Learn more about let declarations

6. Lambda Expressions

Anyone familiar with JavaScript has encountered the issue of understanding exactly what this is. By default, scope is at a function level, so this.x has a different meaning in a nested function. Lambda expressions not only simplify the definition of functions, but also capture outer scope for a consistent hierarchy of variable access.

🔗 Learn more about “this” and arrow functions

7. String Templates

In TypeScript, as with modern JavaScript, you can use string templates for interpolation. This gives you a cleaner way to embed variables and evaluate expressions for output. TypeScript will turn it into string concatenation for older JavaScript versions and leverage the new syntax for modern targets.

🔗 Learn more about string templates

8. Generic Types

Generics, or “generic types” are a development/compile-time feature that I like to think of as syntax to implement the strategy pattern. It involves building a template for a type that opens a new world of possibilities when the type is resolved. The resulting JavaScript doesn’t contain any notation or syntax, but as you will see in this video the use of generics can help quickly capture and fix defects before they are sent to production.

🔗 Learn more about generics

9. Custom Types with Generics

To simplify the code, a custom type is created that uses generics to define a predicate. You can think of a predicate as a test. Given an item T it returns either true or false. This type can then be used to define the second parameter in the find function. The result? Source code that is easier to read and maintain with no changes to the generated JavaScript.

Summary

This concludes part one. Hopefully by now you feel comfortable with TypeScript and can see some of its immediate benefits. Part Two tackles more advanced concepts, including interfaces, “key types,” type guards, strict typing, type decorators and what happens when you target different versions of JavaScript. (The link will be updated here when part 2 is available).

Regards,

Jeremy Likness signature


Top comments (1)

Collapse
 
teroyks profile image
Tero Y

Thanks! This is an extremely demonstrative series. I'll be using this when advocating moving to Typescript to my colleagues.