Defining the Class
Classes act as a containers that encapsulate code.
class Car {
// fields
// consturctor
// properties
// functions
}
Defining Constructor
Constructor are used to initialize fields.
class Car {
// field
engine: string;
// constructor
constructor(engine: string) {
this.engine = engine;
}
}
// shortway to declare a field
class Car {
constructor(public engine: string) { };
}
Defining Functions
Class members are public by default.
class Car {
// fields
engine: string;
// constructor
constructor(engine: string) {
this.engine = engine;
}
// functions. No 'function' keyword require in typescript
start() {
return "Started " + this.engine;
}
stop() {
return "Stopped " + this.engine;
}
}
Defining Properties
Properties act as filters and can have get or set blocks.
class Car {
// private field
private _engine: string;
// constructor
constructor(engine: string) {
this._engine = engine;
}
// properties
get engine(): string {
return this._engine;
}
set engine(value: string) {
if (value == undefined) throw "Supply an Engine!";
this._engine = engine;
}
}
Using Complex Types
We can define complex types and use those inside of classes. Complex type
is just a class that has its own set of members inside of it. It can be fields, properties, functions.
// define a complex type
class Engine {
constructor(public horsePower: number, public engineType: string) { }
}
// use inside the class
class Car {
// private field
private _engine: Engine;
// constructor with complex type
constructor(engine: Engine) {
this._engine = engine;
}
// 'GET' property
get engine(): Engine {
return this._engine;
}
// 'SET' property
set engine(value: Engine) {
if (value == undefined) throw "Please supply an engine";
this._engine = value;
}
// method
start() {
console.log("Engine started: " + this._engine.engine);
}
}
window.onload = function () {
// to use, we need to 'new' up the 'Engine' complex type class
var engine = new Engine(300, "V8");
var car = new Car(engine);
console.log(car.engine.engine); // output: V8
console.log(car.engine.horsePower); // output: 300
console.log(car.engine.start()); // output: Engine started: V8
}
Casting Types
// we need to convert the 'HTMLTableElement'
var table : HTMLTableElement = <HTMLTableElement>document.createElement("table");
// this will fail
var table : HTMLTableElement = document.createElement("table");
Extending Types with TypeScript
Types can be extended using the TypeScript “extends” keyword.
class ChildClass extends ParentClass {
constructor() {
super(); // child class constructor must call base class (super) constructor
}
}
Type Extension Example
// complex type
class Engine {
constructor(public engine: string) { }
}
// parent class
class Auto {
engine: Engine;
constructor(engine: Engine) {
this.engine = engine;
}
}
// truck derives from Auto
class Truck extends Auto {
fourByFour: boolean;
constructor(engine: Engine, fourByFour: boolean){
// call base class constructor
super(engine);
this.fourByFour = fourByFour;
}
}
Demon: Extending Types
// complex type
class Engine {
// this will create two fields because of the public keyword
constructor(public horsePower: number, public engineType: string) { }
// start function with 'callback' function inside
start(callback: (startStatus: boolean, engineType: string) => void) {
// code here for start()
window.setTimeOut( () => {
callback(true, this.engineType);
}, 1000);
}
// stop function with 'callback'
stop(callback: (stopStatus: boolean, engineType: string) => void) {
window.setTimeOut( () => {
callback(true, this.engineType);
}, 1000);
}
}
//
class Accessory {
constructor(public accessoryNumber: number, public title: string) { }
}
//
class Auto {
private _basePrice: number;
private _engine: string;
make: string;
model: string;
accessoryList: string;
// allow user to pass in these values when we "new' up the instance
constructor(basePrice: number, engine: Engine, make: string, model: string) {
this._basePrice = basePrice;
this._engine = engine;
this.make = make;
this.model = model;
}
// a method return a number type
calculateTotal(): number {
var taxRate = .08;
return this._basePrice + (taxRate * this._basePrice);
}
// '...' is rest parameter that acts as array. e.g: addAccessories(new Accessory(), new Accessory(...)) { ... }
addAccessories(...accessories: Accessory[]) {
this.accessoryList = "";
for (var i = 0; i < accessories.length; i++) {
var ac = accessories[i];
this.accessoryList += ac.accessoryNumber + " " + ac.title + "<br />";
}
}
// get the accessory list
getAccessoryList(): string {
return this.accessoryList;
}
// get the base price
get basePrice(): number {
return this._basePrice;
}
// set the base price and we do the check before assign the value to _basePrice field
set basePrice(value: number) {
if (value <= 0) throw "Price must be >= 0";
this._basePrice = value;
}
// get engine
get engine(): Engine {
return this_.engine;
}
// set engine
set engine(value: Engine) {
if (value == undefined) throw "Please supply an engine";
this._engine = value;
}
}
// extends from auto
class Truck extends Auto {
bedLength: string;
fourbyFour: boolean;
constructor(basePrice: number, engine: Engine, make: string, model: string, bedLength: string, fourByFour: boolean){
// need to call super constructor here
super(basePrice, engine, make, model);
this.bedLength = bedLength;
this.fourByFour = fourByFour;
}
}
// on page load
window.onload = function () {
// 'new' up the Truck instance
var truck = new Truck(40000, new Engine(300, "v8"), "Chevy", "Silverado", "Long Bed", true);
console.log(truck.engine.engineType); // output: v8
console.log(truck.bedLength); // output: Long Bed
console.log(truck.calculateTotal().toString()); // output: 43200
// rest params
truck.addAccessories(new Accessory(1234, "Sunroof"), new Accessory(4321, "Towing Package"))
// call the engine start function. In the body we just print out the message
truck.engine.start( (status: boolean, engineType: string) => {
console.log(engineType + " was started");
});
}
Defining Interface
Interfaces provide a way to define a contract
that other objects must implement.
// IEngine Interface defines 2 memebers
interface IEngine {
// start() accepts a single parameter named 'callback' and doesn't return any data
// 'callback' param must be a function that accepts a boolean and a string as params
start(callback: (startStatus: boolean, engineType: string) => void) : void;
stop(callback: (stopStatus: boolean, engineType: string) => void) : void;
}
Optional Members in an Interface
interface IAutoOptions {
engine: IEngine;
basePrice: number;
state: string;
make?: string; // optional
model?: string; // optional
year?: string; // optional
}
Implementing an Interface
Interface provide a way to enforce a “contract”
// make sure we implents all the properties in the interface.
class Engine implements IEngine {
// constructor
constructor(public horsePower: number, public engineType: string) { }
// methods
start(callback: (startStatus: boolean, engineType: string) => void) {
window.setTimeOut( () => {
callback(true, this.engineType);
}, 1000);
}
stop(callback: (stopStatus: boolean, engineType: string) => void) {
window.setTimeOut( () => {
callback(true, this.engineType);
}, 1000);
}
}
Using an Interface as a Type
Interfaces help ensure that proper data is passed.
class Auto {
engine: IEngine;
basePrice: number;
// more fields
constructor(data: IAutoOptions) {
this.engine = data.engine;
this.basePrice = data.basePrice;
}
}
Use Interface to Simplify our Code
Code with the [ADDED] is where we added the new code in.
// [ADDED]
// interface: a contract defines things but not implementation level. The implementation level will be up to the class
interface IEngine {
start(callback: (startStatus: boolean, engineType: string) => void) : void;
stop(callback: (stopStatus: boolean, engineType: string) => void) : void;
}
// complex type
class Engine : IEngine {
// this will create two fields because of the public keyword
constructor(public horsePower: number, public engineType: string) { }
// start function with 'callback' function inside
start(callback: (startStatus: boolean, engineType: string) => void) {
// code here for start()
window.setTimeOut( () => {
callback(true, this.engineType);
}, 1000);
}
// stop function with 'callback'
stop(callback: (stopStatus: boolean, engineType: string) => void) {
window.setTimeOut( () => {
callback(true, this.engineType);
}, 1000);
}
}
// [ADDED]
class CustomEngine implements IEngine {
// start function with 'callback' function inside
start(callback: (startStatus: boolean, engineType: string) => void) {
// code here for start()
window.setTimeOut( () => {
callback(true, "Custom Engine");
}, 1000);
}
// stop function with 'callback'
stop(callback: (stopStatus: boolean, engineType: string) => void) {
window.setTimeOut( () => {
callback(true, "Custom Engine");
}, 1000);
}
}
//
class Accessory {
constructor(public accessoryNumber: number, public title: string) { }
}
//
class Auto {
private _basePrice: number;
private _engine: IEngine; // [ADDED]
make: string;
model: string;
accessoryList: string;
// allow user to pass in these values when we "new' up the instance
constructor(basePrice: number, engine: IEngine, make: string, model: string) {
this._basePrice = basePrice;
this._engine = engine;
this.make = make;
this.model = model;
}
// a method return a number type
calculateTotal(): number {
var taxRate = .08;
return this._basePrice + (taxRate * this._basePrice);
}
// '...' is rest parameter that acts as array. e.g: addAccessories(new Accessory(), new Accessory(...)) { ... }
addAccessories(...accessories: Accessory[]) {
this.accessoryList = "";
for (var i = 0; i < accessories.length; i++) {
var ac = accessories[i];
this.accessoryList += ac.accessoryNumber + " " + ac.title + "<br />";
}
}
// get the accessory list
getAccessoryList(): string {
return this.accessoryList;
}
// get the base price
get basePrice(): number {
return this._basePrice;
}
// set the base price and we do the check before assign the value to _basePrice field
set basePrice(value: number) {
if (value <= 0) throw "Price must be >= 0";
this._basePrice = value;
}
// get engine
get engine(): IEngine {
return this_.engine;
}
// set engine
set engine(value: IEngine) {
if (value == undefined) throw "Please supply an engine";
this._engine = value;
}
}
// extends from auto
class Truck extends Auto {
bedLength: string;
fourbyFour: boolean;
constructor(basePrice: number, engine: Engine, make: string, model: string, bedLength: string, fourByFour: boolean){
// need to call super constructor here
super(basePrice, engine, make, model);
this.bedLength = bedLength;
this.fourByFour = fourByFour;
}
}
// on page load
window.onload = function () {
// 'new' up the Truck instance
var truck = new Truck(40000, new Engine(300, "v8"), "Chevy", "Silverado", "Long Bed", true);
console.log(truck.engine.engineType); // output: v8
console.log(truck.bedLength); // output: Long Bed
console.log(truck.calculateTotal().toString()); // output: 43200
// rest params
truck.addAccessories(new Accessory(1234, "Sunroof"), new Accessory(4321, "Towing Package"))
// call the engine start function. In the body we just print out the message
truck.engine.start( (status: boolean, engineType: string) => {
console.log(engineType + " was started");
});
// [ADDED]
var auto = new Auto(40000, new Engine(250, "Type"), "Make", "Model", "AZ", 2010);
// IEngine only have start() and stop(). We need to cast from interface (IEngine) to Engine type to get the horsePower
var myEngine = <Engine>auto.engine;
console.log(myEngine.horsePower.toString());
}
Extending an Interface
interface IAutoOptions {
engine: IEngine;
basePrice: number;
state: string;
make?: string;
model?: string;
year?: string;
}
// extending an interface: Defines IAutoOptions members plus custom members
interface ITruckOptions extends IAutoOptions {
bedLength?: string;
fourByFour: boolean;
}
Using an Extended Interface
class Truck extends Auto {
bedLength: string;
fourByFour: boolean;
// extended interface
constructor(data: ITruckOptions) {
super(data);
this.bedLength = data.bedLength;
this.fourByFour = data.fourByFour;
}
}
Demo: Extending an Interface
// interface: a contract defines things but not implementation level. The implementation level will be up to the class
interface IEngine {
start(callback: (startStatus: boolean, engineType: string) => void) : void;
stop(callback: (stopStatus: boolean, engineType: string) => void) : void;
}
// [ADDED]
interface IAutoOptions {
basePrice: number;
engine: IEngine;
state: string;
make: string;
model: string;
year: number;
}
// [ADDED]
interface ITruckOptions extends IAutoOptions {
bedLength: string;
fourByFour: boolean;
}
// complex type
class Engine : IEngine {
// this will create two fields because of the public keyword
constructor(public horsePower: number, public engineType: string) { }
// start function with 'callback' function inside
start(callback: (startStatus: boolean, engineType: string) => void) {
// code here for start()
window.setTimeOut( () => {
callback(true, this.engineType);
}, 1000);
}
// stop function with 'callback'
stop(callback: (stopStatus: boolean, engineType: string) => void) {
window.setTimeOut( () => {
callback(true, this.engineType);
}, 1000);
}
}
// [ADDED]
class CustomEngine implements IEngine {
// start function with 'callback' function inside
start(callback: (startStatus: boolean, engineType: string) => void) {
// code here for start()
window.setTimeOut( () => {
callback(true, "Custom Engine");
}, 1000);
}
// stop function with 'callback'
stop(callback: (stopStatus: boolean, engineType: string) => void) {
window.setTimeOut( () => {
callback(true, "Custom Engine");
}, 1000);
}
}
//
class Accessory {
constructor(public accessoryNumber: number, public title: string) { }
}
//
class Auto {
private _basePrice: number;
private _engine: IEngine;
make: string;
model: string;
accessoryList: string;
// [ADDED] IAutoOptions
// allow user to pass in these values when we "new' up the instance
constructor(options: IAutoOptions) {
this._basePrice = options.basePrice;
this._engine = options.engine;
this.make = options.make;
this.model = options.model;
}
// a method return a number type
calculateTotal(): number {
var taxRate = .08;
return this._basePrice + (taxRate * this._basePrice);
}
// '...' is rest parameter that acts as array. e.g: addAccessories(new Accessory(), new Accessory(...)) { ... }
addAccessories(...accessories: Accessory[]) {
this.accessoryList = "";
for (var i = 0; i < accessories.length; i++) {
var ac = accessories[i];
this.accessoryList += ac.accessoryNumber + " " + ac.title + "<br />";
}
}
// get the accessory list
getAccessoryList(): string {
return this.accessoryList;
}
// get the base price
get basePrice(): number {
return this._basePrice;
}
// set the base price and we do the check before assign the value to _basePrice field
set basePrice(value: number) {
if (value <= 0) throw "Price must be >= 0";
this._basePrice = value;
}
// get engine
get engine(): IEngine {
return this_.engine;
}
// set engine
set engine(value: IEngine) {
if (value == undefined) throw "Please supply an engine";
this._engine = value;
}
}
// extends from auto
class Truck extends Auto {
bedLength: string;
fourbyFour: boolean;
constructor(options: ITruckOptions){
// need to call super constructor here
super(options);
this.bedLength = options.bedLength;
this.fourByFour = options.fourByFour;
}
}
// on page load
window.onload = function () {
// [ADDED]
var truck = new Truck({
engine: new Engine(250, "v6),
basePrice: 45000,
state: "Washington",
make: "Ford",
model: "F-150",
year: 2013,
bedLength: "Short bed",
fourByFour: true
});
console.log(truck.bedLength); // output: Short bed
}
Summary