Learn TypeScript — The Ultimate Beginners Guide : Object-oriented Programming
Published: 2022-06-18 17:52:59


![Typescript OOP](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dpri7g4bl5ltykwf03r3.png)


## 1. Object-oriented Programming

As we know `JavaScript` does'nt have the concept of `classes` like other programming languages such as ( PHP, Java, C++, C# ... ).

with `ES6` you can defined `classes` but it's just a syntactic sugar for creating `constructor function` and `prototypal inheritance`.

Let's see `OOP` in `TypeScript` :

### 1- Creating Classes and objects :

```typescript
class Account {
  id: number;
  owner: string;
  balance: number;

  constructor(id: number, owner: string, balance: number) {
    this.id = id;
    this.owner = owner;
    this.balance = balance;
  }

  deposit(amount: number): void {
    if (amount > 0) {
      this.balance += amount;
    }

    throw new Error("Invalid amount");
  }
}

let account = new Account(1, "zineddine", 100);

account.deposit(100);

console.log(typeof account); // object
console.log(account instanceof Account); // true

/*

always make sure to use instanceof property to check if 
an object is an instance of a class

*/
```

`Note :` You can't use the `function` keyword inside a `class` to declare a `function`, use it only when you declare a `stand-alone function`.


### 2- Read-only and Optional Properties :


```typescript
class User {
  readonly id: number;
  name: string;
  email: string;
  nickname?: string; // optional property

  constructor(id: number, name: string, email: string) {
    this.id = id;
    this.name = name;
    this.email = email;
  }
}

let user = new User(1, "zineddine", "hz_haddad@esi.dz");
user.id = 12; // Cannot assign to 'id' because it is a read-only property
```

### 3- Access Control Keywords :


```typescript
class Account {
  /*
    public # by default
    private
    protected
  */

  id: number;
  private _balance: number;

  constructor(id: number, balance: number) {
    this.id = id;
    this._balance = balance;
  }

  deposit(amount: number): void {
    if (amount > 0) {
      // assume we want also to log the transaction
      this._balance += amount;
    }

    throw new Error("Invalid amount");
  }

  private calculateTax(amount: number): number {
    return amount * 0.1;
  }

  getBalance(): number {
    return this._balance;
  }
}

let account = new Account(1, 100);
account._balance -= 50; // Property '_balance' is private and only accessible within class 'Account'
```

### 4- Parameter Properties and Getters & Setters :


```typescript
class Account {
  nickname?: string; // optional property

  constructor(
    public readonly id: number,
    public owner: string,
    private _balance: number
  ) {}

  get balance(): number {
    return this._balance;
  }

  set balance(value: number) {
    if (value < 0) {
      throw new Error("Balance cannot be negative");
    }
    this._balance = value;
  }
}

let account = new Account(1, "zineddine", 100);

console.log(account.balance); // 100
account.balance = -100; // throws error
account.balance = 100; // OK
```

### 5- Index Signatures :
Index Signatures are just a fancy name for `dynamic properties`


```typescript
class NameByNumber {
  // index signature property
  [name: string]: number;
}

let nameByNumber = new NameByNumber();

nameByNumber.John = 1;
// nameByNumber.['John'] = 1;
// nameByNumber.John = '1'; Type 'string' is not assignable to type 'number'
nameByNumber.Jane = 2;
nameByNumber.Bob = 3;

console.log(nameByNumber.John); // 1
```

### 6- Static Members :


```typescript
class Ride {
  private static _activeRides: number = 0;

  start() {
    Ride._activeRides++;
  }

  end() {
    Ride._activeRides--;
  }

  static get activeRides() {
    return Ride._activeRides;
  }
}

let ride1 = new Ride();
let ride2 = new Ride();

ride1.start();
ride2.start();

console.log(Ride.activeRides); // 2
```

### 7- Inheritance and Methods Overriding :


```typescript
class Person {
  constructor(public firstName: string, public lastName: string) {}

  get fullName() {
    return this.firstName + " " + this.lastName;
  }

  walk() {
    console.log("Walking");
  }
}

class Student extends Person {
  constructor(firstName: string, lastName: string, public id: number) {
    super(firstName, lastName);
  }

  override walk() {
    super.walk();
    console.log("Walking on the stairs");
  }

  override get fullName() {
    return "Student : " + super.fullName;
  }
}

let student = new Student("John", "Doe", 123);

console.log(student.fullName);
student.walk();

/*

  Walking
  Walking on the stairs

*/

console.log(student instanceof Person); // true
```

### 8- Polymorphism :


```typescript
// parent class , base class , super class
class Person {
  protected steps: number = 0;

  constructor(public firstName: string, public lastName: string) {}

  get fullName() {
    return this.firstName + " " + this.lastName;
  }
}

// child class , sub class , derived class
class Student extends Person {
  constructor(firstName: string, lastName: string, public id: number) {
    super(firstName, lastName);
  }

  override get fullName() {
    return "Student : " + super.fullName;
  }
}

class Teacher extends Person {
  constructor(firstName: string, lastName: string, public id: number) {
    super(firstName, lastName);
  }

  override get fullName() {
    return "Teacher : " + super.fullName;
  }
}

function printName(persons: Person[]) {
  for (let person of persons) {
    console.log(person.fullName);
  }
}

printName([
  new Person("John", "Doe"),
  new Student("Jane", "Doe", 123),
  new Teacher("John", "Doe", 123),
]);

/*

John Doe
Student : Jane Doe
Teacher : John Doe

*/
```

### 9- Abstract Classes :


```typescript
abstract class Shape {
  constructor(public color: string) {}

  abstract render(): void;
}

class Circle extends Shape {
  constructor(public radius: number, color: string) {
    super(color);
  }

  override render(): void {
    console.log("Circle");
  }
}

let shape = new Shape("red"); // Cannot create an instance of an abstract class
```

### 10- Interfaces :


```typescript
interface Calender {
  name: string;
  addEvent(event: string): void;
  removeEvent(event: string): void;
}

interface CloudCalender extends Calender {
  sync(): void;
}

class GoogleCalender implements CloudCalendar {
  constructor(public name: string) {}

  addEvent(event: string): void {
    console.log(`Adding ${event} to GoogleCalendar`);
  }
  removeEvent(event: string): void {
    console.log(`Removing ${event} from GoogleCalendar`);
  }
  sync(): void {
    console.log("Syncing GoogleCalendar");
  }
}
```

`Note :` In `TypeScript`, `interfaces` and `type aliases` can be used interchangeably.
Both can be used to describe the shape of an object

```typescript
interface Person {
  name: string;
}

let person: Person = {
  name: "Zineddine",
};

type User = {
  name: string;
};

let user: User = {
  name: "Zineddine",
};
```

That’s it for the this chapter !

Github link : [TypeScript-Fundamentals-in-One-Place](https://github.com/haddadzineddine/TypeScript-Fundamentals-in-One-Place)