Introduction to TypeScript

A Four-Part Guide for Experienced JavaScript Developers

Ashok Khanna
5 min readMay 28, 2022

TypeScript is a programming language developed and maintained by Microsoft. It is a strict syntactical superset of JavaScript and adds optional static typing to the language. It is designed for the development of large applications and transpiles to JavaScript.

In this article, we provide a succinct introduction to the language, referring readers to official documentation for further reading. Familiarity with modern Javascript (ES2015+) is expected and one can learn more about JavaScript at Mozilla’s Developer Network.

Starting off with TypeScript

As TypeScript (TS) is a superset of JavaScript (JS), you can begin by using little to none TS in your code and slowly migrate to more of its features. You do need a development environment that transpiles TS to JS, and JetBrains’ WebSStorm is my personal recommendation, but there are many other fine editors you can use.

At its core, TypeScript allows you to add types to your code, which allows the TypeScript compiler to statically check typing during compiliation. By this we mean TypeScript checks your code for type errors during compile-time, and not during run-time (that is where dynamic checks are done).

Annotating your code with types allows the compiler to follow the flow of values through a program and verify that functions and other programming constructs receive and return values of the types annotated to them by the programmer (or inferred by the compiler). A suprising number of bugs are caught by type checking, and as a former non-believer, I now wholeheartedly support static typing checking in JavaScript and code exclusively in TypeScript.

Adding Types to JavaScript — Part 1

TypeScript has a very natural syntax that will remind you of other statically typed languages. Below are some examples of how to add types to various JavaScript constructs.

Primitive Typing

The primitive types in TypeScript are string, number and boolean and can be annotated to variables as follows.

const text: string;
const amount: number;
const loggedIn: boolean;

Type Inference

Often we do not need to explicitly annotate types and can allow the compiler to infer them:

const text = "Hello, World!";
const amount = 1000;
const loggedIn = False;

Usually a sufficiently capable editor such as WebStorm will provide many typing hints (typically by leveraging TSLint) that will help you in determining when to add explicit types or rely on the compilers inferred types. For example, if you have a variable that can be either a string or an array of strings, you probably do not want the following type inference:

const text = "A" // TypeScript infers text is of type string

Rather, you would want to explicitly state the type of the variable as follows.

const text: string | Array<string> = "A"

Array & Union Types

In the above, we introduced two new concepts. The format for array types is Array<type> where type represents the type of the elements of the array (string in the above example). Secondly, union types are created with |. Another example would be:

const primitive: string | number | boolean;

In the above example, the variable primitive can be a string, number or a boolean. Now, this is an important point: when using union types, any operation must be valid on every type in that union. For example, the below will be a type error because numbers and booleans do not have a method toUpperCase:

console.log(primitive.toUpperCase());      // <-- Type Error

To get around this, you would have to do something like:

if (typeof primitive === "string") {
console.log(primitive.toUpperCase());
}

This example is a small illustration of how type checking prevents bugs in code as it prevents some illegal operations at runtime — without the above type guard, JavaScript would throw an error at runtime if primitive stored a number and we tried calling toUpperCase on it.

The ANY Type

To round out this section, we note that TypeScript has the any type which effectively lets you bypass all type checking. It usually is not a good idea to use the any type, but you may have to in some instances (but try to avoid it!).

let obj: any = { x: 0 };// None of the following lines of code will throw compiler errors.
// Using `any` disables all further type checking, and it is assumed
// you know the environment better than TypeScript.
obj.foo();
obj();
obj.bar = 100;
obj = "hello";
const n: number = obj;

Adding Types to JavaScript — Part 2

We covered primitive, array and union types so far. We will now introduce other basic concepts and also show you how to create your own types.

Adding Types to Functions

Below is an example of adding types to a function that accepts three arguments of type number, number and string and returns a value of type number.

function add(x: number, y: number, message: string):number {
console.log(message);
return x + y;
}

Creating Custom Types

We can create our own types with type aliases and interfaces. Both of these do very similar things, with a key distinction that type aliases cannot be re-opened later to add new properties whilst interfaces are always extendable.

type Point {
x: number;
y: number;
}
interface Point {
x: number;
y: number;
}

Thus, we can add types to objects as follows:

const point: Point// Equivalent to the below anonymous object type:const point: { x: number, y: number }

We can also create literal types out of strings and numbers, which are particularly useful in unions. They can be combined with non-literal types.

type leftAlignment = "left";   // Only permitted value is "left"type alignment = leftAlignment | "right" | "center"type validNum = -1 | 0 | 1type validInput = Point | validNum | 5    // Refer 'Point' def above

Adding Types to Classes

The above concepts naturally extend to classes.

class PointAdder {
x: number;
y: number;

constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
adder(a: number): number {
return this.x + this.y + a;
}
}

Note that classes themselves are types:

const test: PointAdder;

Next Steps

The above was a basic but incomplete introduction to TypeScript. In Part 2, we will expand on how TypeScript actually works and then introduce some more advanced concepts like type guards and type assertions. Grab a coffee and jump back in!

--

--

Ashok Khanna

Masters in Quantitative Finance. Writing Computer Science articles and notes on topics that interest me, with a tendency towards writing about Lisp & Swift