Introduction to TypeScript by Winston Levi

81
Introduction to TypeScript by Winston Levi This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi. [email protected]

Transcript of Introduction to TypeScript by Winston Levi

Introduction to TypeScriptby Winston Levi

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

[email protected]

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

TypeScript is converted into JavaScript at compile time. JavaScript is an implementation of the ECMAScript standard. There are three versions of ECMAScript that you will come across when dealing with TypeScript.

It is the version supported in most browsers. When TypeScript compiles into JavaScript, it uses the ECMAScript 3 standards by default.

The following browsers support all the important features of ECMAScript 5 :

• Internet Explorer 9 and above. • Firefox 4 and above. • Opera 12 and above. • Safari 5.1 and above. • Chrome 7 and above.

Older versions of these browsers have only partial support for this standard.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

ECMAScript 6 - Commonly referred to as "ES6", also known as ECMAScript Harmony. New to this Version:• Modules and classes part of the JavaScript language. TypeScript gives you immediate access to these new features, in practically all browsers.

For browser's compatibility to the ECMAScript 6 follow this link:https://kangax.github.io/compat-table/es6/

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Keep in mind to check checkbox

indicating 'Compile on save' which compiles your TypeScript file into JavaScript file on each file save.

Check checkbox indicating

'Allow implicit "any" types' to allow you to have undeclared variables in your code.

Uncheck checkbox indicating

'Allow implicit "any" types' so that compiler will catch any instance where you did not declare the variable type in your TypeScript code.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Figure #1 TypeScript Life Cycle

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

TypeScript is referred as optionally statically typed, which means you can ask the compiler to ignore the type of a variable if you want to take advantage of dynamic typing in a particular circumstance. This mix of static and dynamic typing is already present in .NET; for example, C# is statically typed but allows dynamic types to be declared with the dynamickeyword.

As well as compile-type checking, the language constructs allow static analysis that makes it possible for development tools to highlight errors in your code at design time without the need for compilation.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #1 - Logging Function

function log(message) {

if (typeof window.console !== 'undefined') {

window.console.log(message);

}

}

var testLog = 'Hello world';

log(testLog);

Which compiles to the following JavaScript code

Table 1: Types in Code sample #1

Name Tooltiplog (message: any) => void

message any

window.console Console

testLog string

There are several benefits to this type knowledge when it comes to writing your code. Firstly, if you try to assign a value to testLog that isn’t a string type, you will get a design-time warning and a compilation error.

Figure #2 Precise autocompletion

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #2 - Logging Function

function log(message: string) {

if (typeof window.console !== 'undefined') {

window.console.log(message);

}

}

var testLog = 'Hello world';

log(testLog);

Which compiles to the same JavaScript code as previous example

Table 2: Types in Code sample #2

Name Tooltiplog (message: sting) => void

message sting

window.console Console

testLog string

Code sample #3 - Function Call Type Checking

// allowed

log('Hello world');

// not allowed

log(1);

log(true);

log({'key': 'value'});

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #4 - Entirely Explicit Types

function log(message: string): void {

if (typeof window.console !== 'undefined') {

window.console.log(message);

}

}

var testLog: string = 'Hello world';

log(testLog);

For both examples - the produced JavaScript code remains the same as been shown before.

Code sample #5 - Pragmatic Explicit Types

function log(message: string): void {

if (typeof window.console !== 'undefined') {

window.console.log(message);

}

}

var testLog = 'Hello world';

log(testLog);

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

TypeScript has five built-in primitive types as well as the dynamic any type, and the void return type.

TypeScript Primitive Types:• number• boolean• string• null• undefined• enum

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #6 - Use of Null and Undefined The allowed declarations compiles into following JavaScript code, the not allowed part does not compiles:// allowed

var a: string = null;

var b: number = undefined;

// not allowed

var c: null;

var d: undefined;

// has a value of undefined

var e: string;

In fact, as long as the wrong code exists in TypeScript

file, it will not compile into JS file.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

interface ILogger { }

class Logger { }

var loggerA: ILogger;

var loggerB: Logger;

// has a value of undefined

var e: string;

module MyModule {

}

var example: MyModule = MyModule;

Code sample #7 – Custom Types Using Interfaces and Classes Code sample #8 – Using a Module as a Type

This declarative code does not compiles into JS code. It is more for

your own feature code and variable consistency, prevention of

wrong type value assignment and variable tooltip.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Another advanced type declaration allows you to specify that

the type is a function. You do this by surrounding the definition

in curly braces; for example, a function accepting a string

parameter and not returning any value would have the following

type declaration:

var exampleA: string[] = [];

Unlike other languages you may be using, the variable is initialized

using either the array literal of empty square brackets [] or the new

Array(10) constructor if you wish to specify the array length. The

type is not used on the right-hand side of the statement.

var exampleA: { (name: string): void; } = function (name: string) { };

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Here are some examples of

advanced type declarations in action:

class Logger { }

// exampleA's type is an array of Logger object.var exampleA: Logger[] = [];exampleA.push(new Logger());exampleA.push(new Logger());

// exampleB's type is a function. It accepts an argument of type string and returns a number.var exampleB: { (input: string): number; };

exampleB = function (input: string) {return 1;

};

// exampleC's type is an array of functions. Each function accepts a string and returns a number.var exampleC: { (input: string): number; } [] = [];

var exampleCFunction(input: string): number; {return 10;

}exampleC[0] = exampleCFunction;exampleC[1] = exampleCFunction;

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

A helpful addition to the standard set of datatypes from

JavaScript is the 'enum'. Like languages like C#, an

enum is a way of giving more friendly names to sets of

numeric values.

enum Color {Red, Green, Blue};

var c: Color = Color.Green;

Changing the memmbers numbering order

enum Color {Red = 1, Green, Blue};

var c: Color = Color.Green;

Or, even manually set all the values in the enum:

enum Color {Red = 1, Green = 2, Blue = 4};

var c: Color = Color.Green;

A handy feature of enums is that you can also go from a

numeric value to the name of that value in the enum.

enum Color {Red = 1, Green, Blue};

var colorName: string = Color[2];

alert(colorName);

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Hello World of Generics

function identity(arg: number): number {

return arg;

}

function identity(arg: any): any {return arg;

}

function identity<T>(arg: T): T {return arg;

}

Once we've written the generic identity function, we can

call it in one of two ways. The first way is to pass all of the

arguments, including the type argument, to the function:

var output = identity<string>("myString");

// type of output will be 'string'

The second way is also perhaps the most common. Here we

use 'type argument inference', that is, we want the compiler

to set the value of T for us automatically based on the type

of the argument we pass in:

var output = identity("myString");

// type of output will be 'string'

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

What if we also want to log the length of the argument 'arg'

to the console with each call. We might be tempted to write

this:When you begin to use generics, you'll notice that when you

create generic functions like 'identity', the compiler will

enforce that you use any generically typed parameters in the

body of the function correctly. That is, that you actually treat

these parameters as if they could be any and all types.

Let's take our 'identity' function from earlier:

Working with Generic Type Variables

function identity<T>(arg: T): T {

return arg;

}

function loggingIdentity<T>(arg: T): T {

console.log(arg.length);

// Error: T doesn't have .length

return arg;

}

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

We can alternatively write the sample example this way:Let's say that we've actually intended this function to work on

arrays of T rather that T directly. Since we're working with arrays,

the .length member should be available. We can describe this just

like we would create arrays of other types:

function loggingIdentity<T>(arg: Array<T>): Array<T> {console.log(arg.length);// Array has a .length, so no more errorreturn arg;

}function loggingIdentity<T>(arg: T[]): T[] {

console.log(arg.length);

// Array has a .length, so no more error

return arg;

}

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

We could also have used a different name for the generic type

parameter in the type, so long as the number of type

variables, and how the type variables are used line up.

The type of generic functions is just like those of non-generic

functions, with the type parameters listed first, similarly to

function declarations:

Generic Types

function identity<T>(arg: T): T {return arg;

}

var myIdentity: <T>(arg: T)=>T = identity;

function identity<T>(arg: T): T {return arg;

}

var myIdentity: <U>(arg: U)=>U = identity;

We can also write the generic type as a call signature of an

object literal type:

function identity<T>(arg: T): T {return arg;

}

var myIdentity: {<T>(arg: T): T} = identity;

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Which leads us to writing our first generic interface. Let's take the object literal from the previous example and move it to an interface:

Generic Types

interface GenericIdentityFn {<T>(arg: T): T;

}

function identity<T>(arg: T): T {return arg;

}

var myIdentity: GenericIdentityFn = identity;

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

In a similar example, we may want to move the generic

parameter to be a parameter of the whole interface. This lets us

see what type(s) were generic over (e.g. Dictionary<string>

rather than just Dictionary). This makes the type parameter

visible to all the other members of the interface.

Generic Types

interface GenericIdentityFn<T> {(arg: T): T;

}

function identity<T>(arg: T): T {return arg;

}

var myIdentity: GenericIdentityFn<number> = identity;

In addition to generic interfaces, we can also create generic

classes. Note that it is not possible to create generic enums

and modules.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

A generic class has a similar shape to a generic interface.

Generic classes have a generic type parameter list in angle

brackets (<>) following the name of the class.

Generic Classes

This is a pretty literal use of the 'GenericNumber' class, but

you may have noticed that nothing is restricting it, to only use

the 'number' type. We could have instead used 'string' or

even more complex objects.class GenericNumber<T> {

zeroValue: T;

add: (x: T, y: T) => T;

}

var myGenericNumber = new GenericNumber<number>();

myGenericNumber.zeroValue = 0;

myGenericNumber.add = function(x, y) { return x + y; };

var stringNumeric = new GenericNumber<string>();

stringNumeric.zeroValue = "";

stringNumeric.add = function(x, y) { return x + y; };

alert(stringNumeric.add(stringNumeric.zeroValue,

"test"));

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Generic Constraints

Instead of working with any and all types, we'd like

to constrain this function to work with any and all

types that also have the '.length' property. As long

as the type has this member, we'll allow it, but it's

required to have at least this member. To do so, we

must list our requirement as a constraint on what T can

be.

function loggingIdentity<T>(arg: T): T {

console.log(arg.length);

// Error: T doesn't have .length

return arg;

}

To do so, we will create an interface that describes our constraint.

Here, we will create an interface that has a single '.length' property

and then we will use this interface, and the 'extends' keyword to

denote our constraint:

interface Lengthwise {

length: number;

}

function loggingIdentity<T extends Lengthwise>(arg: T): T {

console.log(arg.length);

// Now we know it has a .length property, so no more error

return arg;

}

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Generic Constraints

Because the generic function is now constrained, it will no longer work over any and all types:

loggingIdentity(3); // Error, number doesn't have a .length property

Instead, we need to pass in values whose type has all the required properties:

loggingIdentity({length: 10: value: 3});

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Using Type Parameters in Generic Constraints

In some cases, it may be useful to declare a type parameter that is constrained by another type parameter. For example,

function find<T, U extends Findable<T>>(n: T, s: U) { // errors because type parameter used in constraint

// ...

}

find(giraffe, myAnimals);

This code is not strictly identical, as the return type of the first function could have returned 'U', which the

second function pattern does not provide a means to do.

You can achieve the pattern above by replacing the type parameter with its constraint. Rewriting the example above,

function find<T>(n: T, s: Findable<T>) {

// ...

}

find(giraffe, myAnimals);

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

When creating factories in TypeScript using generics, it is

necessary to refer to class types by their constructor functions.

For example,

Using Class Types in Generics

function create<T>(c: {new(): T; }): T {

return new c();

}

A more advanced example uses the prototype property to infer

and constrain relationships between the constructor function

and the instance side of class types.

class BeeKeeper {hasMask: boolean;

}

class ZooKeeper {nametag: string;

}

class Animal {numLegs: number;

}

class Bee extends Animal {keeper: BeeKeeper;

}

class Lion extends Animal {keeper: ZooKeeper;

}

function findKeeper<A extends Animal, K> (a: {new(): A; prototype: {keeper: K}}): K {

return a.prototype.keeper;}

findKeeper(Lion).nametag; // typechecks!

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

In the following code, find out how you can model

mixins in TypeScript. After the code, we will break it

down, to understand how it works.

Mixin Sample

Along with traditional OO hierarchies, another popular

way of building up classes from reusable components is to

build them by combining simpler partial classes. You may

be familiar with the idea of mixins or traits for

languages like Scala, and the pattern has reached some

popularity in the JavaScript community.

// Disposable Mixinclass Disposable {

isDisposed: boolean;dispose() {

this.isDisposed = true;}

}

// Activatable Mixinclass Activatable {

isActive: boolean;activate() {

this.isActive = true;}deactivate() {

this.isActive = false;}

}

Sample Part #1

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

class SmartObject implements Disposable, Activatable {constructor() {

setInterval(() => console.log(this.isActive + " :" +this.isDisposed), 500);

}

interact() {this.activate();

}

// DisposableisDisposed: boolean = false;dispose: () => void;// ActivatableisActive: boolean = false;activate: () => void;deactivate: () => void;

}

applyMixins(SmartObject, [Disposable, Activatable])

var smartObj = new SmartObject();// implement activate method from Activatable class // using interact methodsetTimeout(() => smartObj.interact(), 1000);

Sample Part #2 Sample Part #3

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Sample Part #4

/////////////////////////////////////////////////////////

// Register this code somewhere in your runtime library

/////////////////////////////////////////////////////////

function applyMixins(derivedCtor: any, baseCtors: any[]) {

baseCtors.forEach(baseCtor => {

Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {

derivedCtor.prototype[name] = baseCtor.prototype[name];

})

});

}

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

The code sample starts with the two classes that will act

as our mixins. You can see that each one focuses on a

particular activity or capability. We will later mix these

together to form a new class from both capabilities.

Understanding the Sample // Disposable Mixinclass Disposable {

isDisposed: boolean;dispose() {

this.isDisposed = true;}

}

// Activatable Mixinclass Activatable {

isActive: boolean;activate() {

this.isActive = true;}deactivate() {

this.isActive = false;}

}

Sample Part #1

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

class SmartObject implements Disposable, Activatable {constructor() {

setInterval(() => console.log(this.isActive + " :" +this.isDisposed), 500);

}

interact() {this.activate();

}

// DisposableisDisposed: boolean = false;dispose: () => void;// ActivatableisActive: boolean = false;activate: () => void;deactivate: () => void;

}

applyMixins(SmartObject, [Disposable, Activatable])

var smartObj = new SmartObject();// implement activate method from Activatable class // using interact methodsetTimeout(() => smartObj.interact(), 1000);

Sample Part #2 Sample Part #3

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Sample Part #4

/////////////////////////////////////////////////////////

// Register this code somewhere in your runtime library

/////////////////////////////////////////////////////////

function applyMixins(derivedCtor: any, baseCtors: any[]) {

baseCtors.forEach(baseCtor => {

Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {

derivedCtor.prototype[name] = baseCtor.prototype[name];

})

});

}

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

The code sample starts with the two classes that will act

as our mixins. You can see that each one focuses on a

particular activity or capability. We will later mix these

together to form a new class from both capabilities.

Understanding the Sample // Disposable Mixinclass Disposable {

isDisposed: boolean;dispose() {

this.isDisposed = true;}

}

// Activatable Mixinclass Activatable {

isActive: boolean;activate() {

this.isActive = true;}deactivate() {

this.isActive = false;}

}

Sample Part #1

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Next, we are creating the class that will handle the combination of the two mixins. Let's look at this in more detail to see how it does

this:

Understanding the Sample continued

class SmartObject implements Disposable, Activatable {

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Understanding the Sample continued Finally, we mix our mixins into the class, creating the full

implementation by calling to the following function.

applyMixins(SmartObject, [Disposable, Activatable])

// Disposable

isDisposed: boolean = false;

dispose: () => void;

// Activatable

isActive: boolean = false;

activate: () => void;

deactivate: () => void;

Properties and their types declaration for the members

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Understanding the Sample continued

This function is needed somewhere in program from where it can be accessed by all the mixins – it has to be included only once.

This function may be wrapped within a module or a class, if you want it.

function applyMixins(derivedCtor: any, baseCtors: any[]) {

baseCtors.forEach(baseCtor => {

Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {

derivedCtor.prototype[name] = baseCtor.prototype[name];

})

});

}

The Important bits of this example are:

• You use the implements keyword, not the extends keyword.• You need to have a matching signature to keep the compiler quiet (but it does not need real implementation – it will get that from the mixin).• You need to call applyMixins with the correct arguments.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

For variables and parameters that are initialized with a value, TypeScript will infer the type from the initial value. For example,

TypeScript infers the correct types for all of the following examples by inspecting the initial value even if the initial value comes from

another variable:

Code sample #8 – Type Inference

class ExampleClass {}

function myFunction(parameter = 5) { // number}

var myString = 'Hellow World'; // stringvar myBool = true; // booleanvar myNumber = 1.23; // numbervar myExampleClass = new ExampleClass(); // ExampleClassvar myStringArray = ['hello', 'world']; // string[]

var anotherBool = myBool; // boolean

The compiled code in JavaScript

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #9 – Inferred Any Type

The compiled code in JavaScript

var example; // any

example = 'string'; // still any

Code sample #10 – Inferred Any Type

function example (myBool: boolean) { // any

if (myBool) {

return 'hello'; // string

}

return 1; // number

}

There will be no JavaScript code since there is a conflict with returned type.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #11 – Contextual Typing Type inference uses a widened type when the initial value of a

variable, parameter, or function return value is deemed to be

null or undefined. In these cases, the dynamic any type is

used.

Code sample #12 – Widened Types

var func: { (param: number): number; };

func = function (a) { // a is inferred to be number,

// based on the type declaration

// of the func variable.

return a++;

}

var a = undefined; // any

var b = null; // any

var c = [null, null]; // any[]

var d = { a: undefined; b: 1 }; // { a: any; b: number }

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

If you are writing a large-scale application, you can nest your

modules just like you nest namespaces in .Net.

The aim should be to make the components of your program easy

to discover using autocompletion. For a discussion on Modules I

will name the program Succinctly and the first module

Utilities.

Code sample #13 – Utilities Module

Declaring a Module

module Sunccinctly {

module Utilities {

}

}

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

To add a class to a module, you use the class keyword. You can

then place variables and functions inside the class.

Code sample #14 – Logger Class (Utilities.ts)

Adding a Class to a Module

module Utilities {export class Logger {

log(message: string):void {if (typeof window.console !== 'undefined') {

window.console.log(message);}

}}

}

Code sample #15 – Calling the Logger

///<reference path="Utilities.ts" />

Window.onload = function () {

var logger = new Utilities.Logger();

logger.log('Logger is loaded');

};

This gives you powerful code organization tools that closely

match those available in .NET - you can imagine what the entire

TypeScript program might look like:

• Utilities.Logger

• Utilities.Dates

• Messaging.Ajax

• Messaging.JsonConverter

• Messagin.XmlConverter

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Private FunctionsCode sample #16 – Private Function

module Utilities {export class Logger {

log(message: string): void {if (typeof window.console !== 'undefined') {

window.console.log(this.getTimeStamp() + '-' + message);}

}

private getTimeStamp(): string {var now = new Date();

return now.getHours() + ':' +now.getMinutes() + ':' +now.getSeconds() + ':' +now.getMilliseconds();

}}

}

Type safety, interfaces, and protection

of private variables and functions only

occurs at design time and compilation

time in TypeScript.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

If you run the latest example, you will see

that the message is now prefixed with a

timestamp, but that the format isn’t quite

right: 15:39:1:767 - Logger is loaded. When

the hours, minutes, or seconds are less than

two digits, or when the milliseconds are less

than three digits, the value should be left-

padded with zeros to preserve the time

stamp format.

Static Functions

Code sample #17 – Static Function

module Utilities {export class Logger {log(message: string): void {

if (typeof window.console !== 'undefined') {window.console.log(this.getTimeStamp() + '-' + message);

}}

private getTimeStamp(): string {var now = new Date();return Formatter.pad(now.getHours(), 2, '0') + ':' +

Formatter.pad(now.getMinutes(), 2, '0') + ':' +Formatter.pad(now.getSeconds(), 2, '0') + ':' +Formatter.pad(now.getMilliseconds(), 3, '0');

}}

class Formatter {static pad(num: number, len: number, char: string): string {

var output = num.toString();while (output.length < len) {

output = char + output;}return output;

}}

}

Currently available only in this module since export keyword is omitted

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Static Functions

The compiled code in JavaScript

In JavaScript Formatter is exposedfor all, since in JavaScript there is no

Type Safety

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

// beforereturn Formatter.pad(now.getHours(), 2, '0') + ':' +

Formatter.pad(now.getMinutes(), 2, '0') + ':' +Formatter.pad(now.getSeconds(), 2, '0') + ':' +Formatter.pad(now.getMilliseconds(), 3, '0');

// afterreturn Formatter.pad(now.getHours()) + ':' +

Formatter.pad(now.getMinutes()) + ':' +Formatter.pad(now.getSeconds()) + ':' +Formatter.pad(now.getMilliseconds(), 3);

Code sample #18 – Default Parameters

Default Parameters

Code sample #19 – Calling a function that has default parameters

// beforestatic pad(num: number; len: number, char: string) {

// afterstatic pad(num: number; len: number = 2, chart: string = '0') {

This new declaration do not affect the compiled JavaScript

code. It is useful for TypeScript code validation and tooltip.

Using an equal sign after type declaration you assign default value

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #20 – Optional Parameters

Optional Parameters

static pad(num: number, len: number = 2, char?: string) {

if (!char) {char = '0';

}}

Here I check for presence of argumentusing If block, and set value if it wasn't

passed (like default value)

The compiled code in JavaScript

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Rest Parameters

Code sample #21 – Rest Parameters

function addManyNumbers(…numbers: number[]) {var sum = 0;for (var i = 0; i < numbers.length; i++) {

sum += numbers[i];}return sum;

}

var result = addManyNumbers(1,2,3,5,6,7,8,9); // 41

The compiled code in JavaScript

Code sample #22 – Mixed Normal and Rest Parameters

function addManyNumbers(name: string, …numbers: number[]) {

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Function Overloads

To illustrate one potential use for function

overloads, imagine that the pad function could be

called either with a string to pad, or a number to

pad.

Code sample #22 – Function Overloads

static pad(num: number, len?: number, char?: string);static pad(num: string, len?: number, char?: string);static pad(num: any, len: number = 2, char: string = '0'): string {

var output = num.toString();while (output.length < len) {

output = char + output;}return output;

}

The compiled code in JavaScript

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Function Overloads

Code sample #23 – Default Parameters

// beforestatic pad(num: number; len: number, char: string) {

// afterstatic pad(num: number; len: number = 2, chart: string = '0') {

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Function Overloads

Code sample #24 – Alternative to Function Overloads

The compiled code in JavaScript

static padNumber(num: any, len?: number, char?: string): string {return padString(num.toString(), len, char);

}

static padString(input: string, len: number = 2, char: string = '0'): string {var output = input;while (output.length < len) {

output = char + output;}return output;

}

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

ConstructorsCode sample #25 – Constructor

export class Logger{constructor (private formatter: Formatter) {}

log(message: string): void {if (typeof window.console !== 'undefined') {

window.console.log(this.getTimeStamp() + ' – ' + message);}

}

private getTimeStamp(): string {var now = new Date();

return this.formatter.pad(now.getHours()) + ':' +this.formatter.pad(now.getMinutes()) + ':' +this.formatter.pad(now.getSeconds()) + ':' +this.formatter.pad(now.getMilliseconds(), 3);

}}

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Constructors

The compiled code in JavaScript

To create an instance of the Logger class, you are required

to pass in a Formatter. The development tools and

compiler will check that you do.

Code sample #26 – Calling a Constructor

var formatter = new Utilities.Formatter();var logger = new Utilities.Logger(formatter);

Remember, you will need to add the export keyword

to the formatter.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Interfaces

Interfaces declared using the interface keyword and you

can make an interface available outside of a module using the

export keyword, just as you can with a class.

Code sample #27 – Ilogger Interface

export interface ILogger {

log(message: string): void;

}

Code sample #28 – Implementing Ilogger Interface

export class Logger implements ILogger {

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Interfaces

Code sample #30 – New Logger Class implementing multiple interfaces

Code sample #29 – New Logger Class

export class AnnoyingLogger implements ILogger {

log(message: string): void {

alert(message);

}

}

Multiple Interfaces

In TypeScript a class can implement more than one interface. To

do this, separate each interface with a comma:

export class MyClass implements IFirstInterface, ISecondInterface {

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Duck Typing

Code sample #31 – Duck Typing

interface IPerson {firstName: string;lastName: string;

}

class Person implements IPerson {constructor(public firstName: string, public lastName: string) {}

}

var personA: IPerson = new Person('Jane', 'Smith'); // explicitvar personB: IPerson = { firstName: 'Jo', lastName: 'Smith' }; // duck typing

function printName(personObj: IPerson) {console.log(personObj.firstName);

}

It is worth pointing out that the

type-checker doesn't require that

these properties come in any sort of

order, only that the properties the

interface requires are present and have

the required type.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Inheritance and Polymorphism

Code sample #32 – Inheritance and Polymorphism

export class AnnoyingLogger extends Logger {

log(message: string): void {

alert(message);

super.log(message);

}

}

To inherit from a class, you use the extends keyword. The log

function alerts the user before calling the base Logger class,

which you can access with the super keyword. The result of

this function is that an alert dialog will be displayed, and when

it is closed, a message will be added to the console, if one is

running.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Inheritance and Polymorphism

Code sample #33 – Calling the Logger

///<reference path='Utilities.ts'/>

window.onload = function () {

var logger: Utilities.ILoggeer = new Utilities.AnnoyingLogger();

Logger.log('Logger is loaded');

}

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #34 – Interface InheritanceMultiple Inheritanceinterface IMover {

mover() : void;}

interface IShaker {shake() : void;

}

interface IMoverShaker extends IMover, IShaker {}

class MoverShaker implements IMoverShaker {mover() {}

shake() {}

}

Because the IMoverShaker interface inherits from both IMover and

IShaker, the class must implement both the move function and the

shake function. This is a powerful feature that allows you to compose a

number of interfaces into a super interface.

A class can only inherit from one other class; it is not possible

to inherit from multiple classes

One interesting feature that TypeScript has that you won’t find in

.NET is the ability for an interface to inherit from another interface. Just

like class inheritance, you use the extends keyword to do this. Rather

than attempting to override or extend the behavior of a base class, you

would use interface inheritance to compose interface groups. Unlike

classes, interfaces can inherit from multiple interfaces.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Super Inheritance

Figure #3 A Super Interface

The super interface in this diagram is the

IAmphibian interface. A class that implements this

super interface can do everything shown on the

right-hand side of the diagram. Without the super

interface, it would be hard to express that a class

needed both IBoat and ICar interfaces to be valid

for a given operation.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #35 – Instance Of

Using instanceof

The instanceof keyword can be used to compare an

instance to a known type. It will return true if the instance is of

the known type, or inherits from the known type. For

example, the AnnoyingLogger class is an instance of

AnnoyingLogger, and it is also an instance of Logger.

var isLogger = logger instanceof Utilities.Logger; // true

var isLogger = logger instanceof Utilities.AnnoyingLogger; // true

var isLogger = logger instanceof Utilities.Formatter; // false

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

There are different ways of packaging your program depending

on where you are planning on running it. It is easier if you

decide on your packaging strategy up front as it may lead to a

subtly different program structure. So far I have used examples

that suit the first of the packaging techniques: bundling. This is

the technique you are most likely to use if you are writing

applications using ASP.NET MVC (bundling was introduced in

version 4).

The main differences packages can make to you TypeScript

program are:

• Module declaration style

• Module reference style

• Script loading style

I will describe how to do these three thing for each of the

packaging techniques here.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Module Declaration Style

To use a bundling strategy in your program, you can declare the

modules as you have seen in the examples in this book.Code sample #37 – Main.ts

Code sample #36 – MyModule.ts

Module Referencing Style

module MyModule {

export class MyClass {

}

}

/// <reference path="MyModules.ts" />

var myClass = new MyModule.MyClass();

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Script Loading Style

Code sample #38 – BundleConfig.cs

public class BundleConfig{

public static void RegisterBundles(BundleCollection bundles){

bundles.Add(new ScriptBundle("~/MyProgram").Include("~/Scripts/MyModule.js", "~/Scripts/Maing.js"));}

}

If you want to include all scripts in a given directory, you can use a

wildcard character in your bundle registration, although this will not

guarantee any ordering like an explicit bundle would.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Script Loading Style

Code sample #39 – Bundle Using Wildcard Character

public class BundleConfig

{

public static void RegisterBundles(BundleCollection bundles)

{

bundles.Add(new ScriptBundle("~/bundles/MyProgram").Include("~/Scripts/*"));

}

}

Code sample #40 – Using the Bundle

@Script.Render("~/bundles/MyProgram")

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

CommonJS is intended to provide a common standard library for JavaScript that makes it

easier to run as a server-side language, command-line tool, or desktop application. The

most famous implementation of CommonJS is the highly scalable Node.js, which runs on

Google’s V8 JavaScript engine.

http://www.commonjs.org/

If you are targeting a platform such as Node.js, which implements a CommonJS runtime

module loader, you can tell the TypeScript compiler to generate code that works out of the

box with CommonJS. To do this, add a module switch to the TypeScript compiler command

in your project file.

<Exec Command="&quot;$(PROGRAMFILES)\Microsoft SDKs\TypeScript\tsc&quot; --

module commonjs @(TypeScriptCompile ->'&quot;%(fullpath)&quot;', ' ')" />

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #41 – MyModule.ts

Module Declaration Style

export class MyClass {

}

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #42 – Main.ts

Module Reference Style

import myModule = module('MyModule'); // MyModule.ts

var myClass = new myModule.MyClass();

Script Loading Style

All of the scripts required by your Main.js file will be automatically

loaded by the CommonJS library.

Summary

TypeScript’s CommonJS support is tailored for platforms such

as Node.js, although there are many more implementations

that you may not have heard of, such as Narwhal and

CouchDB.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

AMD stands for Asynchronous Module Definition and is an API that allows your modules

to be loaded asynchronously on an as needed basis. This is actually a pattern adapted

from CommonJS intended to be used in web browsers.

To use AMD, you will need to add a module-loader to your program, such as RequireJS.

http://requirejs.org/

To get AMD output from the TypeScript compiler, set the module mode to “amd” in your

project file.

<Exec Command="&quot;$(PROGRAMFILES)\Microsoft SDKs\TypeScript\tsc&quot; --

module amd @(TypeScriptCompile ->'&quot;%(fullpath)&quot;', ' ')" />

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #43 – MyModule.ts

Module Declaration Style

export class MyClass {

}

Code sample #44 – Main.ts

Module Reference Style

import myModule = module('MyModule'); // MyModule.ts

var myClass = new myModule.MyClass();

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Script Loading Style

<script src="Scripts/require.js" data-main="Scripts/Main"></script>

Specify your main program file

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

If you are designing a program that will run on the server, as well as in a browser, you can

write your modules in the CommonJS style, and use the TypeScript compiler to give you the

CommonJS and the AMD flavors of compiled JavaScript without having to change your code.

While your TypeScript remains unchanged between the two platforms, the CommonJS

output will use the built-in require function, while the AMD output will call RequireJS.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #45 – Simple Ambient Declaration

declare var externalLogger;

externalLogger.anything();

Code sample #46 – Ambient Class Definition

declare class ExternalLogger {log(message: string): void;

}

declare var externalLogger: ExternalLogger;

externalLogger.anything();

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Code sample #47 – Ambient Class Definition

declare module ExternalUtilities {export class ExternalLogger {

public totalLogs: number;log(message: string): void;

}}

var externalLogger = new ExternalUtilities.ExternalLogger();

externalLogger.log("Hello World");var logCount = externalLogger.totalLogs;

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

You can place your ambient declaration in a separate file. If you do so, you should use a .d.ts file extension, for example,

ExternalLogger.d.ts. This file can then be referenced or imported just like any other TypeScript file.

Code sample #48 – Referencing Ambient Declaration File

/// <reference path="ExternalLogger.d.ts" />

var externalLogger = new ExternalUtilities.ExternalLogger();

externalLogger.log("Hello World");

externalLogger.anything();

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Figure #3 A Super Interface

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Open Visual Studio 2013

Open Tools menu Extensions and Updates… sub menu and follow the steps described in following image

You can also download this file directly from TypeScript Language website at http://www.typescriptlang.org/

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Installing the extension adds TypeScript language support to the Visual Studio. Now there is a support for new Project Type and File Templates.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.

Adding TypeScript File to the Solution.

Right click on the Solution in Solution Explorer window, Select Add and from sub-menu select TypeScript File as seen in image.

This document contains proprietary and confidential information and may not be copied or distributed without the permission of Winston Levi.