An Introduction to TypeScript: Static Typing for the Web

Share this article

An Introduction to TypeScript: Static Typing for the Web
TypeScript is one of many attempts at creating a better experience with JavaScript.
TypeScript is a strongly-typed superset of JavaScript, which means it adds some syntactical benefits to the language while still letting you write normal JavaScript if you want to. It encourages a more declarative style of programming through things like interfaces and static typing (more on these later), offers modules and classes, and most importantly, integrates relatively well with popular JavaScript libraries and code. You could think of it as a strongly static layer over current JavaScript that has a few features to make life (and debugging especially) a bit more bearable. TypeScript gained particular attention a few years ago because it was selected for full support by Angular 2 and following (which is also written in TypeScript itself). It’s also developed by Microsoft, which means it has the backing of two major tech companies (not a bad place for any language). Since this time, it’s gained more of a following and mainstream status. Needless to say, TypeScript is definitely worth looking into.

How Does it Work?

TypeScript actually looks much like modern JavaScript. At the most basic level, it introduces a static typing paradigm to JavaScript, so instead of the following:
var name = “Susan”,
    age = 25,
    hasCode = true;
We could write the following:
let name: string = "Susan",
    age: number = 25,
    hasCode: boolean = true;
As you can see, there’s not a whole lot of difference here. All we’re doing is explicitly telling the system what type each variable is; we’re telling it from the get-go that name is a string and age is a number. But that just seems like we have to write more code. Why bother telling the system such specific information? Because it gives the system more information about our program, which in turn means it can catch errors that we might make further down the road. Imagine, for instance, you have something like this in your code:
var age = 25;
age = "twenty-five";
Mutating a variable like this and changing its type will likely end up breaking stuff somewhere else, especially in a really big program, so it’s great if the compiler can catch this before we load this up in our browser and have to sit for half an hour looking for the issue ourselves. Basically, it makes our program safer and more secure from bugs. There’s more, though. Here’s an example from the TypeScript website intro tutorial (which you can find here):
interface Person {
    firstname: string;
    lastname: string;
}

function greeter(person : Person):string {
    return "Hello, " + person.firstname + " " + person.lastname;
}

let user = {firstname: "Jane", lastname: "User"};

document.body.innerHTML = greeter(user);
Now there are a few more unusual things here than we had before. We’ve got a run-of-the-mill object, called user, containing a first and last name, and that’s being passed to greeter() and the output inserted into the body of the document. But there is some bizarre-looking stuff in the arguments of thegreeter function, as well as something called an interface. Let’s start with the greeter function:
function greeter(person: Person):string {
    return "Hello, " + person.firstname + " " + person.lastname;
}
We can see that greeter takes a person parameter and we expect it to be of type Person. In this way, we can be sure that when we ask for that person’s first name, it will definitely be there and we won’t induce headaches upon ourselves if it fails. The :string after the function parameters tells us what type we expect this function to return when we call it. The body of the function is nothing complicated but, of course, by now you’re probably wondering what on earth a Person type actually is. This is where the interface feature comes in:
interface Person {
    firstname: string;
    lastname: string;
}
Interfaces are used in TypeScript to define the structure of objects (and only objects). In this example, we’re saying that any variable of type Person must be an object containing a firstname and a lastname property, both of the string type. We’re basically creating a custom type for our object. This is useful because it tells the compiler, as well as yourself and any developer who will work on this in the future, exactly what type of data to expect. We’re basically modelling the object properties, creating something we can reference if we need to debug later. This is often why you’ll see interfaces at the top of TypeScript files, as they give us a good idea of the data the program is working with in the rest of the file. In our example, if we use this Person interface with a variable at any point in the program and it doesn’t contain either a firstname or lastname, both of type string (our user object thankfully does), then the compiler will moan at us and we will be forced to mend our ways. Not only that, but having static typing means that an IDE or editor with support for TypeScript will be able to provide us with very good, very specific hinting and auto-completion so that we can develop code that is both faster and safer. There are many more features that TypeScript allows us to use, such as generics and namespaces, so at least a quick read of their documentation is highly recommended.

How Do I Set it Up?

Because TypeScript is a superset of JavaScript, we’ll need to transpile it into JavaScript if we want to use it in the browser. Thankfully, it integrates well with a number of task runners and bundlers already. If you’re just looking to play around with it locally first in particular, you can install TypeScript globally via npm and use it from the command line with the tsc command, like so:
tsc your-typescript-file.ts
This will output a JavaScript file, in this case called your-typescript-file.js, which you can then use in the browser as per usual. Setting it up in a project, though, will almost certainly entail setting up a proper tsconfig.json. This file denotes that the project is a TypeScript project, and allows us to set a number of configuration options. Here’s a truncated example from the docs:
{
    "compilerOptions": {
        "module": "commonjs",
        "outFile": "./build/local/tsc.js",
        "sourceMap": true
    },
    "exclude": [
        "node_modules"
    ]
}
Here we’re configuring the compiler in a number of ways. We’re specifying a module system to compile to, where to put the compiled file when it’s finished and to include a source map. We’re also giving it an exclude option, which basically tells the compiler to compile any TypeScript files — those ending in .ts — it finds as long as they’re not in the node_modules
folder. From here, we can integrate things into our favorite task runner or bundler. Both Grunt and Gulp have plugins for TypeScript which will expose the compiler options for your task runners. Webpack has an awesome TypeScript loader, and there’s good support for some other setups as well. Basically, you can get TypeScript integrated into pretty much any workflow you currently have going on without too much effort.

External Typings

If you’re using external libraries in your project (let’s be honest, who isn’t?) you’ll likely also need some type definitions. These definitions — denoted by a .d.ts extension — give us access to interfaces that other people have written for a number of JavaScript libraries. By and large, these definitions are available in a gigantic repo called DefinitelyTyped, which is where we install them from. To use them you’ll need to install Typings, which is kind of like npm but for TypeScript type definitions. It has its own config file, called typings.json, where you can configure your bundles and paths for type definition installation. We won’t go into too much detail here, but if we wanted to use AngularJS 1.x types, for example, we could simply go typings install angularjs --save and have them downloaded into a path defined in typings.json. After that, you could use Angular’s type definitions anywhere in your project simply by including this line:
/// <reference path="angularjs/angular.d.ts" />
Now we can use Angular type definitions like the following:
var http: ng.IHttpService;
Any developers who happen upon our code at a later stage (or ourselves, three months after we’ve written it) will be able to make more sense of what we’ve written by looking at them.

Okay, What About the Community?

The TypeScript community is continuing to grow, as is the language’s adoption. Perhaps most importantly, it’s what Angular 2+ is written in and the framework provides full support for it straight from the beginning. There is also fantastic support for its syntax baked into Microsoft Visual Studio IDE and Visual Studio Code, with packages and plugins for editors like Atom, Sublime Text and Emacs readily available as well. What this means is that there’s plenty of activity going on around TypeScript, so this is something you’ll want to keep your eye on.

Further Reading

Conclusion

TypeScript is an interesting push toward improving on JavaScript’s shortcomings by introducing a static typing system, complete with interfaces and type unions. This helps us write safer, more legible and declarative code. It integrates well with virtually every mainstream build setup out there at the moment and even gives us the ability to create and use custom types as well. There are also a myriad IDEs and text editors that have great support for its syntax and compile process, so you can use it in your coding environment of choice with little pain or process. Perhaps most importantly, TypeScript is a big part of Angular 2+, which means we’ll continue to see it well into the future. The more we know about it and how it works, the better equipped we’ll be to deal with it when it arrives as a fully-fledged mainstream alternative to JavaScript. Do you feel inspired to use TypeScript in your next project? Is strong typing the future of JavaScript, or is it just a fad? Let me know what you think below!

Frequently Asked Questions about TypeScript and Static Typing

What is the main difference between static typing and dynamic typing in TypeScript?

Static typing and dynamic typing are two fundamental concepts in programming languages. In static typing, the type of a variable is known at compile time. This means that you have to declare the type of the variable when you define it. TypeScript is a statically typed language. On the other hand, in dynamic typing, the type is associated with run-time values, and not named variables/fields themselves. This means you don’t have to declare the type of the variable when you define it. JavaScript is a dynamically typed language.

How does static typing benefit TypeScript?

Static typing brings several benefits to TypeScript. It helps catch errors at compile time rather than at runtime, which can save a lot of debugging time. It also provides better tooling with features like code navigation, autocompletion, and refactoring, which can significantly improve developer productivity. Moreover, static typing can make the code more readable and self-documenting by providing explicit information about how the data should be handled.

Can TypeScript work without static typing?

Yes, TypeScript can work without static typing. TypeScript is a superset of JavaScript, which is a dynamically typed language. This means that any valid JavaScript code is also valid TypeScript code. However, without static typing, you would lose the benefits that TypeScript provides, such as early error checking, better tooling, and improved code readability.

How does TypeScript achieve optional static typing?

TypeScript achieves optional static typing through the use of type annotations. Type annotations are a way to explicitly specify the type of a variable. If you don’t provide a type annotation, TypeScript will use a feature called type inference to automatically infer the type based on the initial value of the variable. This makes static typing in TypeScript optional.

What is the syntax for type annotations in TypeScript?

In TypeScript, you can add a type annotation to a variable by appending a colon and the type after the variable name. For example, let name: string = 'John'; declares a variable named name of type string with an initial value of ‘John’.

What types does TypeScript support?

TypeScript supports all the basic types that JavaScript supports, including number, string, boolean, null, and undefined. In addition, TypeScript introduces some new types like any, unknown, never, void, enum, tuple, and array. TypeScript also supports advanced types like union types, intersection types, type aliases, and type guards.

How does TypeScript handle type errors?

TypeScript uses a static type checker to check the types of variables at compile time. If a type error is detected, TypeScript will report it as a compile error. This allows you to catch and fix type errors before the code is run.

Can I use TypeScript with existing JavaScript libraries?

Yes, you can use TypeScript with existing JavaScript libraries. TypeScript provides a way to describe the shape of JavaScript objects with declaration files (.d.ts files). These files allow you to use existing JavaScript libraries in your TypeScript code without losing the benefits of static typing.

How does TypeScript improve code maintainability?

TypeScript improves code maintainability by making the code more readable and self-documenting. With static typing, you can easily understand what type of data a function expects and what type of data it returns. This makes the code easier to understand and maintain. Moreover, TypeScript’s tooling features like autocompletion and refactoring can also help maintain the code.

Is it hard to learn TypeScript if I already know JavaScript?

If you already know JavaScript, learning TypeScript should be relatively easy. TypeScript is a superset of JavaScript, which means that any valid JavaScript code is also valid TypeScript code. The main new thing you need to learn is TypeScript’s type system, which is not too complex and can bring significant benefits to your development process.

Byron HouwensByron Houwens
View Author

Byron Houwens is a designer and developer who enjoys focusing on front end technologies and UX. He currently works as a front end developer in the burgeoning edtech environment, and lives in sunny Cape Town, South Africa.

angularangular-hubLearn AngularnilsonjTypeScript
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week