Table of Contents Preface typescript angular

Type System

JavaScript is a dy­nam­i­cally typed lan­guage, which means it al­lows vari­ables and ob­jects und change their prop­er­ties and be­hav­iour on run­time. The fol­low­ing ex­am­ple is valid JavaScript:

let value = 123;
value = 'Hello World!';
value = function ( options ) { ... };

This is a very sim­ple ex­am­ple and could be jus­ti­fied. How­ever, as soon as your ap­pli­ca­tion and team grows, code like this could eas­ily be over­looked and cause er­rors that are hard to find and fix be­cause they only oc­cur on run­time. This is es­pe­cially true if func­tions need a cer­tain call sig­na­ture (line 3) and there is no doc­u­men­ta­tion on how to use it. If you are al­lowed to as­sign var­i­ous types to the same vari­able, you can not be cer­tain later on what type the vari­able is and alawys have to check its type.

Infering Types

Type­Script tries to in­fer as much type in­for­ma­tion as it can in or­der to give to type safety and pre­vent care­less mis­takes. If you run the above snip­pet through the Type­Script com­piler, it will in­fer that the vari­able value has to be a Number. In this case the type in­for­ma­tion will be implicitly ap­plied by Type­Script and the com­piler will throw two er­rors:

Type 'string' is not assignable to type 'number'.
let value: number
Type '(options: any) => void' is not assignable to type 'number'.
let value: number

Types can also be explicit. For this, Type­Script in­tro­duces a very sim­ple syn­tax (see annotations). There are mu­ti­ple rea­sons why you want to en­force a spe­cific type on an ob­ject. One is to en­sure the com­piler sees, what you thought it should see. An­other is to doc­u­ment your code for the next de­vel­oper who has to read it (maybe even fu­ture you!).[1] This also in­cludes us­ing your code as an API or li­brary.

Duck Typing

Es­pe­cially when work­ing with com­plex ob­jects de­vel­op­ers can profit from strong typ­ing. For com­plex vari­ables Type­Script uses a method called duck-typ­ing.

When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.[2]

This means the Type­Script com­piler will check if prop­er­ties have the same set of prop­er­ties. If so, they are con­sid­ered to to of the same type. To il­lus­trate this, red the fol­low­ing ex­am­ple:

let character = {
    name: 'Peter Jason Quill',
    first_appearance: 'January, 1976'
};
character = {
    name: 'Groot',
    first_appearance: 'November, 1960'
};

If you would try to as­sign an ob­ject to character that is miss­ing one of the two prop­er­ties (name, first_appearance), the com­piler would throw an er­ror. How­ever as­sig­ing an ob­ject with an ad­di­tional prop­erty is al­lowed:

character = {
    name: 'Rocket Raccoon',
    first_appearance: 'Summer, 1976',
    group_affililations: 'Guardians of the Galaxy'
};

Annotations

Type­Script uses an­no­ta­tions to en­force a cer­tain type on a vari­able, in­clud­ing ar­rays. Func­tion ar­gu­ments and re­turn val­ues can also be sta­t­i­cally typed. The fol­low­ing ex­am­ple shows how the an­no­ta­tion syn­tax works:

// Variable
let nbr: number = 2;

// Array
let stringArray: string[];
stringArray.push('red');
stringArray.push('blue');

// Function
function power (nbr: number): number {
    return nbr * nbr;
}

Interfaces

In or­der to cre­ate more com­plex types than prim­ites (number, string, boolean), Type­Script also al­lows us to cre­ate own ab­strac types in form of in­ter­faces. An in­ter­face de­fines a set of prop­er­ties and method sig­na­tures an ob­ject must im­ple­ment. If an ob­ject ad­heres to an in­ter­face, it implements that in­ter­face.[3]

Fol­low­ing the ex­am­ple from the duck typing section an ob­ject de­scrib­ing a character could be de­fined by an in­ter­face as fol­lows:

interface ICharacter {
    name: string;
    first_appearance: string;
    group_affililations?: string;
    isVillain(): boolean;
}

To show all pos­si­ble use cases a method isVillain() was added. If you would try to use an ob­ject from the duck typing section with the ICharacter in­ter­face the com­piler would throw an er­ror be­cause none of the character vari­able ime­ple­ments the in­ter­face.

Type '{ name: string; first_appearance: string; }' is not assignable to type 'ICharacter'.
Property 'isVillain' is missing in type '{ name: string; first_appearance: string; }'.
let character: ICharacter

Special types any and void

Type­Script tries re­ally hard to stay out of your way and some­times (be­cause of rea­sons) you need a vari­able to be flex­i­ble en­gough to mix and match its types. For this case, Type­Script has the any key­word. This type is com­pat­i­ble with all other types. Mean­ing that you can as­sign any­thing to a vari­able flagged as any.

let value: any = 123;
value = 'Hello World!';

Fur­ther­more, if a func­tion does not have a re­turn type it should be an­no­tated with :void.

function log (str: string): void { ... }

  1. TypeScript Deep Dive

  2. Heim, Michael (2007). Exploring Indiana Highways p. 68.

  3. "What is an Interface". The Java Tu­to­ri­als. Or­a­cle