2. Watch the full video of the presentation
at:
https://goo.gl/RD7jmr
3. TypeScriptTM is a typed object-oriented superset of
JavaScript that transcompiles to plain JavaScript.
3
4. Installation and use
4
$ npm install -g typescript
function greeter(person) {
return "Hello, " + person;
}
var user = "Jane User";
document.body.innerHTML = greeter(user);
function greeter(person) {
return "Hello, " + person;
}
var user = "Jane User";
document.body.innerHTML = greeter(user);
// greeter.ts // greeter.js
tsc greeter.ts
5. Basic types & Type annotations (I)
Boolean
String & template strings (`)
5
let isDone: boolean = false;
let decimal: number = 6;
let hex: number = 0xf00d;
let binary: number = 0b1010;
let octal: number = 0o744;
Number
let color: string = 'blue';
color = 'red';
let sentence: string = `Hello world!
Today the sky is ${color}.`
let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];
let x: [string, number];
x = ["hello", 10]; // OK
x = [10, "hello"]; // Error
Enum
Tuple
Array
enum Color {Red, Green, Blue};
let c: Color = Color.Green;
// enum Color {Red = 1, Green, Blue};
// enum Color {Red = 1, Green = 3, Blue = 5};
6. You can only assign
‘undefined’ or ‘null’
to a ‘void’ variable...
Basic types & Type annotations (II)
Object
6
let notSure: Object = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
notSure.toFixed(); // compiler error!
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
notSure.toFixed(); // compiler doesn’t check
Any
function warnUser(): void {
alert("This is my warning message");
}
Void
Type assertions
let a: any = "this is a string";
let strLength1: number = (<string>a).length;
let strLength2: number = (a as string).length;
7. Variable declarations
Let vs var → block-scoping (IIFE)
7
function f(shouldInitialize: boolean) {
if (shouldInitialize) var x = 10;
return x;
}
const currentYear = 2016;
currentYear--; // Re-assignment not allowed!
const date = { year: 2016 };
date.year--; // Okay!
Const
Destructuring
1) Array destructuring
2) Object destructuring
- Property renaming
- Default value
3) Function declarations
This surely deserves some more
elaborated examples
function(): string {
if (true) {
var x = 10;
var x = 5; // Okay!
let y = "hola";
let y = "adiós"; // Nope!
}
return y; // Nope, nope!!!
}
for (var i = 0; i < 10; i++)
setTimeout(function() {
console.log(i);
}, 100 * i);
9. Interfaces (II)
Indexable types
9
interface IStringArray {
[index: number]: string;
}
let myArray: IStringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
interface ISquareConfig {
color: string;
width?: number;
[propName: string]: any;
}
let aa: ISquareConfig = {color: 'red', foo: 'bar'};
console.log(aa.color); // red
console.log(aa['color']); // red
console.log(aa['foo']); // bar
Class types
interface IClockInterface {
currentTime: Date;
setTime(d: Date);
}
class Clock implements IClockInterface {
currentTime: Date;
constructor(h: number, m: number) {
// do nothing
}
setTime(d: Date) {
this.currentTime = d;
}
}
10. Interfaces (III)
Extending interfaces
10
interface IShape {
color: string;
}
interface ISquare extends IShape {
sideLength: number;
}
let square = <ISquare>{}; // type assertion
square.color = "blue";
square.sideLength = 10;
Hybrid types
interface Counter {
(start: number): string;
interval: number;
reset(): void;
}
function getCounter(): Counter {
let ctr = <Counter>function (start: number) { };
ctr.interval = 123;
ctr.reset = function () { ... };
return ctr;
}
let c = getCounter();
c(10); // object acting as a
function
c.reset(); // object acting as an
object
c.interval = 5.0; // object acting as an
object
11. Classes
11
class Message {
mssg: string;
constructor(mssg: string) {
this.mssg = mssg;
}
}
class Greeter extends Message {
constructor(message: string) {
super(message);
}
greet() {
return "Hello, " + this.mssg;
}
}
let greeter = new Greeter("world");
greeter.greet();
class Message {
constructor(private mssg: string);// !!!
public printOut(): void {
console.log(this.mssg); //
!!!
}
}
Parameter properties
and static properties...
and static functions...
and abstract classes…
and property initializer (ES7)
class Message {
mssg: string = undefined;
...
public printOut(): void {
console.log(this.mssg);
}
}
12. Functions (I)
12
// named function
function add(x: number, y: number): number {
return x + y;
}
// anonymous function
let add = function(x: number, y: number):
number { return x + y; };
// ...with function type
let add: (x: number, y: number) => number;
add = function(x: number, y: number): number
{
return x + y;
};
// ...letting TypeScript to infer the types
let add: (x: number, y: number) => number;
add = function(x, y) {
return x + y;
};
function buildName(first: string, last = "Smith") {
return first + " " + name;
}
Optional parameters
Default parameters
function buildName(first: string, last?: string) {
if (last)
return first + " " + last;
else
return first;
}
function buildName(first: string, ...rest:
string[]){
return first + " " + rest.join(" ");
}
Rest parameters
13. let deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
createCardPicker: function() {
return function() {
let card = Math.floor(Math.random() * 52);
let suit = Math.floor(card / 13);
return {
suit: this.suits[suit],
card: card % 13
};
}
}
}
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
Functions (II)
Using this (wrongly)
13
Lambda functions
let deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
createCardPicker: function() {
return () => {
let card = Math.floor(Math.random() * 52);
let suit = Math.floor(card / 13);
return {
suit: this.suits[suit],
card: card % 13
};
}
}
}
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
Captures the this available when
the function is created rather than
when it is invoked (ES6).
The this being used in the function
created by createCardPicker will be
set to window1 instead of our deck
object.
1 In strict mode, this will be undefined.
14. Generics
14
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>("myString");
class MyNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myNumber = new MyNumber<number>();
myNumber.zeroValue = 0;
myNumber.add = function(x, y) {
return x + y;
};
function loggingIdentity<T>(arg: T): T {
console.log(arg.length); // Error!
return arg;
}
interface ILengthwise {
length: number;
}
function loggingIdentity<T extends ILengthwise>(arg: T): T {
console.log(arg.length); // Alright!
return arg;
}
15. Type inferences
15
window.onmousedown = function(mouseEvent) {
console.log(mouseEvent.buton); // Err!
};
window.onmousedown = function(mouseEvent: any) {
console.log(mouseEvent.buton); // Ok!
};
Best common type
Contextual Type
let x = [1, 2, null]; // inferred num[]
x[2] = 'hola'; // Err!
let zoo = [new Rhino(), new Elephant(), new Snake()];
// the inferred type could be Rhino[], so we couldn’t do zoo[2].creep()
let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];
// this is better, but still we need to do (zoo[2] as Snake).creep()
16. Advanced types (I)
Union types
16
let input: number | string | boolean;
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
function getSmallPet(): Fish | Bird { … }
let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim(); // error! not in Fish U Bird
(pet as Fish).swim() // okay for the compiler!
let pet = getSmallPet();
if ((<Fish>pet).swim) {
(<Fish>pet).swim();
} else {
(<Bird>pet).fly();
}
Type checking
function isFish(pet: Fish | Bird): pet is Fish {
return (<Fish>pet).swim !== undefined;
}
isFish(pet) ? pet.swim() : pet.fly();
User-defined type guards
typeof and instanceof
17. Advanced types (II)
Intersection types
17
function f<T, U>(first: T, second: U): T & U {
let result = <T & U>{};
for (let id in first)
(<any>result)[id] = (<any>first)[id];
for (let id in second)
if (!result.hasOwnProperty(id))
(<any>result)[id] = (<any>second)[id];
return result;
}
class Person {
constructor(public name: string) { ... }
}
class Logger {
log() { ... }
}
let jim = f(new Person("Jim"), new Logger());
let name = jim.name;
jim.log();
type myTpe = string | () => string;
function getName(n: myType): string {
return typeof n === ‘string’ ? n : n();
}
Type aliases
type Easing = "ease-in" | "ease-out" | "ease-in-
out";
String literal types
18. Symbols (ES6)
Declaration
18
let sym1: symbol = Symbol();
let sym2 = Symbol("key"); // optional string key
let sym = Symbol();
let obj = {
[sym]: "value"
};
console.log(obj[sym]); // "value"
Keys for objects
Uniquity
let sym1 = Symbol("key");
let sym2 = Symbol("key");
sym1 === sym2; // false
A symbol is a unique and immutable data type and may be used as an identifier for object properties.
The Symbol object is an implicit object wrapper for the symbol primitive data type...
...alright!
19. Iterators
for..of (is not for..in)
19
let list: number[] = [4, 5, 6];
for (let i of list) {
console.log(i); // "4", "5", "6"
}
for (let i in list) {
console.log(i); // "0", "1", "2",
}
let numbers = [1, 2, 3];
for (let num of numbers) {
console.log(num);
}
In order to be iterable, an object must implement the @@iterator method, meaning that the object must have a property
with a Symbol.iterator key. Array, Map, Set, String, etc. have their Symbol.iterator property already implemented.
var numbers = [1, 2, 3];
for (var _i = 0; _i < numbers.length; _i++) {
var num = numbers[_i];
console.log(num);
}
targeting ES5 or ES3
*[Symbol.iterator]() {
let i: number = 0;
while(this[i] !== undefined) {
yield this[i]; i++;
}
}
20. Generators
20
While custom iterators are a useful tool, their creation requires careful programming due to the need to explicitly
maintain their internal state. Generators provide a powerful alternative: they allow you to define an iterative algorithm by
writing a single function which can maintain its own state.
A generator is a special type of function that works as a factory for iterators. A function becomes a generator if it
contains one or more yield expressions and if it uses the function* syntax.
function* idMaker(){
var index = 0;
while(true)
yield index++;
}
var gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
function* fibonacci(){
let fn1 = 0, fn2 = 1;
while (true) {
let current = fn1;
fn1 = fn2;
fn2 += current;
yield current;
}
}
let sequence = fibonacci();
console.log(sequence.next().value); // 0
console.log(sequence.next().value); // 1
console.log(sequence.next().value); // 1
21. Modules
21
class ZipCodeValidator {
isAcceptable(s: string) {
return s.length === 5;
}
}
export { ZipCodeValidator };
export { ZipCodeValidator as mainValidator };
Modules (external modules in TypeScript 1.5) are executed within their own scope, not in the global scope; variables,
functions, classes, etc. declared in a module are not visible outside the module unless they are explicitly exported.
Conversely, to consume a variable, function, class, interface, etc. exported from a different module, it has to be
imported.
In TypeScript (and in ES6) any file containing a top-level import or export is
considered a module.
22. Namespaces
22
namespace Validation {
export interface StringValidator {
isAcceptable(s: string): boolean;
}
}
let f: Validation.StringValidator = isAcceptable(s: string): boolean { ... }
Namespaces (internal modules in TypeScript 1.5) are a way to wrap objects avoiding to put lots of different names into
the global namespace.
To declare anything that shall be visible from outside the namespace, we need to use export.
23. Triple-Slash directives
23
Triple-slash directives are single-line comments containing a single XML tag. The contents
of the comment are used as compiler directives.
❖ Triple-slash directives are only valid at the top of their containing file.
❖ A triple-slash directive can only be preceded by single or multi-line comments, including other triple-
slash directives.
❖ If they are encountered following a statement or a declaration they are treated as regular single-line
comments, and hold no special meaning.
/// <reference path=”...” /> serves as a declaration of dependency between files.
Triple-slash references instruct the compiler to include additional files in the compilation process.
They also serve as a method to order the output when using --out or --outFile.
/// <reference path="..." />
24. Map files
24
• Source map files let tools map between the emitted
JavaScript code and the TypeScript source files that
created it.
• Many debuggers (VisualStudio Code or Chrome's dev
tools) can consume these files so you can debug the
TypeScript file instead of the JavaScript file.
• This is the same source map format being produced by
some minifiers and other compiled-to-JS languages like
CoffeeScript.
25. TypeScript definitions & TSD (I)
25
• When using TypeScript, you will need TypeScript definition
files to work with external libraries.
• A lot of those definition files (.d.ts) are available on GitHub:
DefinitelyTyped. At the time of writing, there are 1921
entries. At the time of reviewing (one week later), 1933.
• To use these files in your project, you can simply download
and copy them to your project.
• We can also use TSD, the TypeScript Definitions Manager.
TSD is a package manager to search and install definition
files directly from the DefinitelyTyped repository.
26. TypeScript definitions & TSD (II)
26
# Installation
$ npm install tsd -g
# Create a new tsd.json and tsd.d.ts
$ tsd init
# Get some info about a package
$ tsd query jquery --info --resolve
# Install a package into our project
$ tsd install angular-mock
# Install a package into our project and save it into tsd.json
$ tsd install angular-mock --save
# Install all the references from tsd.json
$ tsd install
27. Typings (I)
27
• Typings is a simpler way to manage and install TypeScript
definitions.
• It uses typings.json, which can resolve to the Typings
Registry, GitHub, NPM, Bower, HTTP and local files.
• Packages can use type definitions from various sources
and different versions.
28. Typings (II)
28
# Install Typings CLI utility
$ npm install typings --global
# Find an available definition by name
$ typings search --name react
# Creates or update the typings.json file from a previous tsd.json file
$ typings init --upgrade
# Install all the typings described in typings.json
$ typings install
30. Sources
• TypeScript 1.8 Language Specification at Microsoft’s GitHub (Jan, 2016):
https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md
• TypeScript Deep Dive (Basarat Ali Syed - Last edition: today!):
https://www.gitbook.com/book/basarat/typescript/details
• Mozilla’s JavaScript Reference:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
All the source code available at Epic Labs’ GitHub soon:
https://github.com/epiclabs-io
30