Large Scale JavaScript with TypeScript

HH.js - July 2013

TypeScript

  • Valid JavaScript is also valid TypeScript
  • Almost ECMAScript 6 with declared types
  • Introduces a compiler step

New Concepts of the Language

  • Declared Types
  • Classes and Inheritance
  • Modules
  • Interfaces
  • External declarations

Declared, Static Typing

var name: string = "Olli";

function doIt(p1: number, p2: boolean, p3: string): string {
    if (p2) {
        return p3;
    } else {
        return "" + p1;
    }
}

Classes

class Person {
    name: string; // public is the default visibility
    private age: number; // either public or private

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }

    toString(): string {
        return "Name: " + this.name;
    }
}

var olli: Person = new Person("Olli", 42);
console.log(olli.name); // => "Olli"
olli.age; // => Error: Person.age' is inaccessible

Inheritance

class Customer extends Person {
    private id: number;

    constructor(name: string, age: number, id: number) {
        super(name, age);
        this.id = id;
    }

    toString(): string {
        return super.toString() + ", id: " + this.id;
    }
}

var c1: Customer = new Customer("Oma", 88, 47);
console.log(c1.toString());  // => "Name: Oma, id: 47"

Static Properties

class Customer extends Person {
    private static sequence: number = 1;
    public static nextNumber(): number {
        return Customer.sequence++;
    }

    private id: number;
    constructor(name: string, age: number) {
        super(name, age);
        this.id = Customer.nextNumber();
    }
    toString(): string {
        return super.toString() + ", id: " + this.id;
    }
}
var c1: Customer = new Customer("Oma", 88);
console.log(c1.toString());

Modules

module CustomerModule {
    class Person {
        // ...
    }

    export class Customer extends Person {
        // ...
    }
}

// new CustomerModule.Person(...); // => undefined
new CustomerModule.Customer(...); // => cool

Structural Typing with Interfaces

interface HasName {
    name: string;
}

var olli: HasName = {name: 'Olli'};

olli.name; // good
olli.age; // not good, as not declared

olli = {name: 'Olli', age: 100};

olli.age; // still not good, as not declared

External Declarations

  • Adds tooling and type checking to existing JavaScript libraries
  • Declarations disappear when compiled
  • TypeScript compiler comes with external declarations for core and DOM libraries (lib.d.ts)
  • Work in progress for a lot of other libraries

Excerpt from lib.d.ts #1

declare function parseFloat(string: string): number;

interface Function {
    apply(thisArg: any, ...argArray: any[]): any;
    call(thisArg: any, ...argArray: any[]): any;
    bind(thisArg: any, ...argArray: any[]): Function;
    prototype: any;
    length: number;
}

Excerpt from lib.d.ts #2

interface Node extends EventTarget {
    nodeType: number;
    previousSibling: Node;
    localName: string;
    parentNode: Node;
    nextSibling: Node;
    // ...
}

Tools

  • tsc: Command Line Tool for Compiler
  • WebStorm / Intellij IDEA
  • Visual Studio (Express for Web)
  • Syntax highlighting for other text editors (Sublime Text, Emacs, Vim)

And there is more...

  • Mapping files
  • External module declarations for AMD / CommonJS
  • Enums
  • Generics
  • Casts
  • All the ES 6 goodness

Resources

These Slides on GitHub: https://github.com/DJCordhose/typescript-hh-js

Code Samples on GitHub: https://github.com/DJCordhose/typescript-sandbox

External Links

Conclusion

  • TypeScript has the same semantics as JavaScript
  • Declared types bring you to the next level of (IDE) tooling
    • Analyzing Code
    • Refactoring
    • Code completion
  • Syntactic sugar for classes, inheritance, and modules is nice
  • All added features aligned to ECMAScript 6
  • Interfaces and external declarations add the benefits of TypeScript to pure JavaScript libraries

Questions / Discussion