Classes

Classes

Classes can "implement" multiple interfaces

class Contact implements HasEmail {
email: string;
name: string;
constructor(name: string, email: string) {
this.email = email;
this.name = name;
}
}

Note : Above is little verbose -- we have to specify the words "name" and "email" 3x.

Typescript shortcut for above

class Contact implements HasEmail {
constructor(public name: string, public email: string) {
}
}

Adds the public variables to class, also auto assigns them in constructor (Check compiled ES6 code if needed)

Access modifiers

  • public : By default variables & methods in classes are public, so can be called from any where. (everyone)

  • protected : can be called from same & inherited class (me and subclasses)

  • private : can be called from same class (only me)

Better use ES # for private & let babel handle it

Class fields

Class fields can have initializers (defaults)

class OtherContact implements HasEmail, HasPhoneNumber {
protected age: number = 0; //default
private password: string;
constructor(public name: string, public email: string, public phone: number) {
// () password must either be initialized like this, or have a default value
this.password = Math.round(Math.random() * 1e14).toString(32);
}
}

Definite assignment operator or others

class OtherContact{
private password: string;
//compiler throws error as password is not assigned with a default in all cases
constructor(public name: string, public email: string, public phone: number) {
if(phone > 0){ //conditional assignment
this.password = "test";
}
}
}

In above scenarios can use Definite assignment operator (!)

class OtherContact{
private password!: string;
//telling compiler that we will surely handle default assignment - u ignore
constructor(public name: string, public email: string, public phone: number) {
if(phone > 0){ //conditional assignment
this.password = "test";
}
}
}

Other alternative is some default OR type

class OtherContact{
private password: string | undefined; //satisfying with OR type
constructor(public name: string, public email: string, public phone: number) {
if(phone > 0){ //conditional assignment
this.password = "test";
}
}
}

Note : also try ts no check style

Leverage getter setters

class OtherContact{
firstName: string;
lastName: string;
get fullName(){ //no setter to make it readonly
return this.firstName + this.lastName;
}
}

Usage: If readonly prop needed, DB & front end prop differs, some built in validations on set for email, phone..etc

Abstract classes

Classes with partial implementation (Think of half classes & half interfaces)

abstract class AbstractContact implements HasEmail, HasPhoneNumber {
public abstract phone: number; // must be implemented by non-abstract subclasses
constructor(
public name: string,
public email: string // must be public to satisfy HasEmail
) {}
abstract sendEmail(): void; // must be implemented by non-abstract subclasses
}

Implementors must "fill in" any abstract methods or properties

class ConcreteContact extends AbstractContact {
constructor(
public phone: number, // must happen before non property-parameter arguments
name: string,
email: string
) {
super(name, email);
}
sendEmail() {
// mandatory!
console.log("sending an email");
}
}