Link Search Menu Expand Document

TypeScript

JavaScript is not typed: you can pass object to a function that expects list and there’ll be no error until the code is run. What this means is that your code can be ‘unsafe’ with errors that are only apparent during run time. TypeScript aims to solve this problem by introducing type safety to JS like C++ or Java. TypeScript is a super set of JS. Therefore, all JS code is valid TypeScript code. Let’s review the TypeScript extra syntax here. Reference

Install TypeScript to your project:

$ npm install typescript --save-dev
$ touch hello.ts
$ npx tsc hello.ts
# hello.ts is compiled to hello.js
$ cat hello.js

Basic Types

There are 3 basic types in TypeScript

//
let isDone: boolean = false;
let lines: number = 42;
let name: string = "Anders";

But you can omit the type annotation if the variables are derived from explicit literals

let isDone = false;
let lines = 42;
let name = "Anders";

If you try to assign a number to boolean, tsc raises an error.

// hello.ts
let isDone = false;
isDone = 2;
$ npx tsc hello.ts
hello.ts:2:1 - error TS2322: Type 'number' is not assignable to type 'boolean'.

2 isDone = 2
  ~~~~~~


Found 1 error.

You can use any type for the variables you want to resign:

let notSure: any = 4;
notSure = "maybe a string instead";

You can have enumerations

enum Color {
  Red,
  Green,
  Blue,
}
let c: Color = Color.Green;

Functions

You can annotate the function outputs types as follows. Here void is used because function returns nothing.

function bigHorribleAlert(): void {
  alert("I'm a little annoying box!");
}

Functions will also try inferring the output type.

let fn = function (i: number) {
  return i * i;
};

Also here’s how you use arrow syntax for functions

let fn = (i: number): number => {
  return i * i;
};

Interfaces

Similar to classes but you don’t have implementation in the declaration. Anything that has the properties is compliant with the interface

interface Person {
  name: string;
  // Optional properties, marked with a "?"
  age?: number;
  // And of course functions
  move(): void;
}

// p is valid Person
let p: Person = { name: "Bobby", move: () => {} };

// but since there's no move here, this is an invalid Person.
// compiler will raise an error.
let invalidPerson: Person = { name: "Bobby", age: 20 };

You can also have interfaces for functions

interface SearchFunc {
  (source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function (src: string, sub: string) {
  return src.search(sub) != -1;
};

Classes

All members are public by default.

class Point {
  // Properties
  x: number;

  // Constructor - the public/private keywords in this context will generate
  // the boiler plate code for the property and the initialization in the
  // constructor.
  // In this example, "y" will be defined just like "x" is, but with less code
  // Default values are also supported

  constructor(x: number, public y: number = 0) {
    this.x = x;
  }

  // Functions
  dist(): number { return Math.sqrt(this.x * this.x + this.y * this.y); }

  // Static members
  static origin = new Point(0, 0);
}

let p1 = new Point(10, 20);

You can also have classes implementing an interface

class PointPerson implements Person {
  name: string;
  move() {}
}

Inheritance is done using extends keyword

class Point3D extends Point {
  constructor(x: number, y: number, public z: number = 0) {
    super(x, y); // Explicit call to the super class constructor is mandatory
  }

  // Overwrite
  dist(): number {
    let d = super.dist();
    return Math.sqrt(d * d + this.z * this.z);
  }
}

Modules

You can use modules for name spacing

module Geometry {
  export class Square {
    constructor(public sideLength: number = 0) {
    }
    area() {
      return Math.pow(this.sideLength, 2);
    }
  }
}

let s1 = new Geometry.Square(5);

// Local alias for referencing a module
import G = Geometry;

let s2 = new G.Square(10);