TypeScript Quick Reference

If you have used ES6/ES2015 with Babel, you will feel right at home with TypeScript. Babel and TypeScript both are transpilers to generate ES5 compatible JavaScript, but TypeScript goes beyond that. TypeScript provides comprehensive typechecker and additional abstractions not part of the ECMA Script specification. If you want strong type system and features like generics, interfaces, decorators, etc. TypeScript is probably what you want to go with. Tooling and developer experience is also another aspect - typecheker enables tooling to give instant feedback on type mismatch or violations. Here are few quick reference notes on TypeScript.

Classes, Abstract Classes and Inheritance

TypeScript classes are mostly same as ES6 with additional features like static properties and abstract classes.

class Contact {
    name: string;                //if no accessor is specified, it's treated as public
    public phoneNumber: string;  //to be explicit, you cold specify public
    private companyName: string; //accessible only within the class

    public static contactType = "Institutional"; //static property accessible at the class-level

    //method with param and return types
    getVCard(formatVersion: string):string {
        return "ToDo: Not implemented";
    }
}

Let’s create an abstract class with few common properties and an abstract method which needs to be implemented by any class inheriting from it.

abstract class Entity {
    id: number;
    createdBy: string;
    createdOn: Date;
    modifiedOn: Date;

    abstract toText():string;
}

Now, we could inherit the Contact from this class, we will have to implement the toText method.

class Contact extends Entity {
    name: string;                //if no accessor is specified, it's treated as public
    public phoneNumber: string;  //to be explicit, you cold specify public
    private companyName: string; //accessible only within the class

    public static contactType = "Institutional"; //static property accessible at the class-level

    //method with param and return types
    getVCard(formatVersion: string):string {
        return "ToDo: Not implemented";
    }

    toText():string {
        return `${this.name} works with ${this.companyName}`;
    }
}

Interfaces

Interfaces is a nice feature - it could contain the properties and methods. Properties could be flagged as optional.

interface ExportProvider {
   format: string;
   version?: number;     //'?' flags this property as optional 
   export(data): string;
}

class ExcelExport implements ExportProvider {
   format: string = "Excel"; 
   //version: number = 1; //we have flagged at optional, so this isn't required

   export(data): string {
      return "ToDo: implement the export"; 
   }
}

Optional and Default Parameters

TypeScript allows to flag parameters to be optional - in that case the value will be undefined. When it’s defaulted, it will assume the assigned value when not passed.

function downloadDocument(id: number, compress: boolean = false, fileName?: string) {
    console.log(`id=${id}, compress=${compress}, fileName=${fileName}`);
}

downloadDocument(101);
downloadDocument(101, true);
downloadDocument(101, true, "docs.zip");

Rest Parameters

Sometimes the number of argument to be passed could vary, rest parameters allows that flexibility. You could specify the types for these parameters, if you no type is specified, the caller could pass the parameters of any type.

//'topics' here is the rest argument of type number
function subscribe(email: string, ...topics:number[]): boolean{
   topics.forEach(t => console.log(t));

   return true; 
}

subscribe('someone@nowhere.com', 102, 223, 424);

//'inputs' is here rest argument without any type requirement
function rankInputs(logicType: string, ...inputs) {
    inputs.forEach(i => console.log(i));
}

rankInputs("fuzzy", true, 101, { percentile: 98.3 });

Constructor Param Properties

You could avoid the boiler plate of accepting the parameters in the constructor and assigning it to the property by simply assigning an accessor to the argument.

class Engine {
    constructor(private id: string, public name:string, public capacity: number) {
        //'id' will be accessible only within this class
        //'name' and 'capacity' will be exposed as a public properties
    }
}

Generics and Constrains

If you have used generics in C# or Java, you know it brings lots of flexibility and reusability to the design. TypeScript generics has very similar feel to C# generics. It supports generic class, generic function and generic interfaces as well.

Generic Function
export function ReadValue<T>(row, column): T {
    //return value must be of type T
}
Generic Class
class ModelHelper<T> {
   validate(model: T) {
       
   } 

  createInstance(model: T): T {
     //return type needs to be of type T 
  } 
}
Generic Interface

Same way you could define the interface with the generic, classes implementing the interface will have to implement the generic as well.

interface Repository<T> {
    Save(T): T;
    Delete(number): boolean;
    Get(number): T;
}
Constrains

You could define the contains around the type of the generic which could be used with the function, class or interface. Let’s redefine the Repository interface from the previous example to enforce a type requirement on generic type T. Keyword extends mandates that the type used with this generic interface must be of type Entity.

interface Repository<T extends Entity> {
    Save(T): T;
    Delete(number): boolean;
    Get(number): T;
}