Skip to main content

Introduction to TypeScript

6 min read

Older Article

This article was published 9 years ago. Some information may be outdated or no longer applicable.

TypeScript is a language developed by Microsoft, and it’s a superset of JavaScript. When we say ‘superset’, we mean TypeScript has all the JavaScript features, but it extends the language with things like interfaces, generics and (one of the most exciting additions in my opinion) typings. We could get more specific and say TypeScript is a superset of ES2015, since many ES2015 features (like arrow functions) are also available in TypeScript.

Before we look at how TypeScript behaves, we need to cover a few key terms and processes that’ll help when building applications with it.

Transpilation

Transpilation is the process of transforming code from one language to another (sometimes called source-to-source compiling). For TypeScript, transpilation is essential: we need to transpile our TypeScript code to JavaScript so browsers and other environments can run it.

During transpilation, we can tell the transpiler how to shape the final JavaScript output by feeding it options.

tsc

tsc is a command line TypeScript compiler with many transpilation options. These options can be added inline or through a tsconfig.json configuration file.

Since tsc is a command line tool, we need to install it. It ships as an npm package when we install TypeScript. It makes sense to install it globally so we can use it in any project that needs TypeScript compilation.

npm i -g typescript
tsc -v

Let’s see how we can generate a JavaScript file from TypeScript. Create this basic TypeScript file:

// app.ts
function greet(name: string): string {
  return `Hello ${name}`;
}

There are some type annotations here. We’ll cover those later.

To generate JavaScript, run tsc app.ts from the command line.

Without any parameters, this produces a file with the same name but a .js extension. Open it up and you’ll see the code has been transformed to plain JavaScript. By default, it gets transpiled down to ES3 (a very old version of JavaScript).

We can change this by adding a flag: tsc --target es6 app.ts. This generates ES6 (ES2015) compatible code.

tsc comes with loads of compile options. Specifying them all on the command line gets tedious, so it makes more sense to keep them in a configuration file.

tsconfig.json

We can load compiler-specific configuration from tsconfig.json. Let’s try it by creating the file with this content:

{
  "compilerOptions": {
    "target": "es6"
  }
}

Running just tsc app.ts now produces ES6 (ES2015) compatible code. Check the following page for other compiler options.

The resulting file (whether the target was es3 or es6) is executable via Node.js. Test it by typing node app.js in the command line. The same app.js file could also be inserted into an HTML page for browser use.

Workflow

As mentioned, we need to transpile TypeScript to JavaScript for browsers (and environments like Node.js) to execute it. There are build tools that handle this, and the one we’ll look at is webpack.

So why not just use tsc? Why bring in another tool? Two reasons.

First, it’s unlikely we’ll only ever need to transpile TypeScript without doing other work for our site (think concatenating CSS files, for example). Webpack lets us add extra steps to the build process.

Second, when we introduce modules in TypeScript code, transpiling a single file isn’t enough. We need to build up a dependency graph of all the files the final JavaScript requires. Webpack handles that too.

Webpack

Webpack is a module bundler that creates a single bundle from multiple sources by building a dependency graph. This concept works for TypeScript and JavaScript, but also for HTML and CSS. At its most basic, webpack needs three configuration items: entry, output, and loader (plus an optional plugin).

Webpack uses a mechanism called tree shaking. It strips unused export statements from the final bundle, producing smaller output. We’ll cover this later.

To work with webpack, install it via npm: npm i -g webpack.

Webpack builds a dependency graph starting from an entry point (think of it as the main application file). For every entry point, we get an output bundle: the generated JavaScript file we can run in the browser or Node.js. The third piece is the loader. Loaders let webpack process files of any type. A loader consists of a module that tests for files and applies transformations to them.

Webpack needs a configuration file, which by default is called webpack.config.js. Here’s what an example configuration looks like:

// webpack.config.js
module.exports = {
  entry: './app.ts',
  output: {
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.ts?$/,
        loader: 'ts-loader',
      },
    ],
  },
};

In plain English: take app.ts as the entry point. For every file with a .ts extension, run it through ts-loader. Bundle the result into bundle.js.

We can then take bundle.js and run it in Node.js or add it to the browser, since it’ll contain valid, executable JavaScript code.

To transpile the TypeScript code, run webpack from the command line in the same directory as webpack.config.js.

Before we try an example, we also need to install the loader via npm. In our case: npm i ts-loader.

Now that we’ve got webpack and ts-loader installed, let’s give it a go.

Create two TypeScript files:

// math.ts:
export class MathsModule {
  sum(...numbers: number[]): number {
    return numbers.reduce((acc, num) => acc + num);
  }
}

// app.ts

import { MathsModule } from './math';

const math = new MathsModule();
console.log(math.sum(4, 5, 6));

A simple application (we’ll explore all the type annotations later). We’ve created a Maths module with a sum function that adds up all the numbers passed as arguments. In the main file (app.ts) we import the module and call the method.

Run webpack from the command line. Once it finishes, you should get a bundle.js file. (Bundle.js contains webpack-related code that’s needed to make the JavaScript run in the browser.)

Sharp-eyed readers will notice that bundle.js contains ES6 (ES2015) code. Webpack picks up the tsconfig.json file we created earlier.

Feel free to run it with Node.js:

$ node bundle.js
15

At the time of writing, browser support for require statements is limited. Even though tsc can generate JavaScript with require() statements, those only work in Node.js, not the browser. You can test this by calling tsc app.ts and running node app.js. Notice math.js also gets created. You could then run browserify to create a browser-specific bundle: browserify app.js -o web-bundle.js (assuming you have browserify installed globally via npm). Webpack does all of this in one step.