Lesson 1
Exploring TypeScript Classes: Structure, Properties, and Methods
Lesson Overview

Greetings! Today, we're revisiting TypeScript classes, the core building block of Object-Oriented Programming (OOP) in TypeScript. Through hands-on examples, we'll explore the fundamental concepts of TypeScript classes, including their structure, properties, and methods, while highlighting TypeScript's powerful type system.

TypeScript Classes Refresher

Let's begin with a refresher on TypeScript classes. Essential to OOP, TypeScript classes bundle relevant data and functions into compact units called objects. Consider a video game character, which is a typical example of a class instance, with specific properties (such as health or strength) and methods (such as attack or defense). TypeScript enhances this model by enabling static typing, which allows us to define types for properties and method parameters.

TypeScript
1class GameCharacter { 2 // constructor method with type annotations 3 constructor(public name: string, public health: number, public strength: number) {} 4 5 attack(otherCharacter: GameCharacter): void { // method with parameter type and return type annotations 6 otherCharacter.health -= this.strength; 7 } 8}

TypeScript classes facilitate the grouping of associated code elements, simplifying their management. Now, to better understand how the above example works, let's go through it step-by-step.

Structure of a TypeScript Class

A TypeScript class serves as a blueprint consisting of properties and methods, with type annotations adding clarity and robustness. While properties represent data relevant to a class instance, methods are actions or functions that manipulate this data. Each class includes a constructor function, which is used to define class properties with type annotations. The constructor initializes the properties when an object is created, and the public keyword automatically creates and assigns the properties to the class instance, eliminating the need for separate declarations. Without public, we would have to declare and assign properties separately inside the constructor.

An essential keyword within these methods is this, which represents the class instance. In object-oriented programming, it's needed to access the class's properties and methods. When a new class instance is created, TypeScript automatically passes it to the this parameter to access individual instance properties and methods using the this keyword. This mechanism allows each object to keep track of its own state and behaviors.

TypeScript
1class GameCharacter { 2 // constructor: defines class properties with type annotations 3 constructor(public name: string, public health: number, public strength: number) {} 4} 5 6const character = new GameCharacter("Hero", 100, 20); // object or instance of the class
Class Properties

Properties in TypeScript classes hold data associated with each class instance. In our GameCharacter class, name, health, and strength are properties, each with a specified type. You can access a class property using the object of the class, followed by a dot (.), and then the property name.

TypeScript
1class GameCharacter { 2 // constructor: defines class properties with type annotations 3 constructor(public name: string, public health: number, public strength: number) {} 4} 5 6const character = new GameCharacter("Hero", 100, 20); // object or instance of the class 7console.log(character.name); // prints: Hero 8console.log(character.health); // prints: 100 9console.log(character.strength); // prints: 20

Using TypeScript's type system, properties ensure type safety by preventing unexpected types and bugs.

Class Methods

A class also contains methods — actions or functions that manipulate the data in the class, with parameters and return types explicitly defined. For example, the attack method in our GameCharacter class simulates an attack by one game character on another.

TypeScript
1class GameCharacter { 2 // constructor: defines class properties with type annotations 3 constructor(public name: string, public health: number, public strength: number) {} 4 5 attack(otherCharacter: GameCharacter): void { // method with parameter type and return type annotations 6 otherCharacter.health -= this.strength; // modifies 'otherCharacter's health property 7 } 8} 9 10const character1 = new GameCharacter("Hero", 100, 20); // First instance of GameCharacter 11const character2 = new GameCharacter("Villain", 80, 15); // Second instance 12 13console.log(character2.health); // prints: 80 14character1.attack(character2); // character1 attacks character2 15console.log(character2.health); // prints: 60

Note: The keyword this refers to the instance of the class where the method is being invoked. For example, if character1.attack(character2) is called, this.strength refers to character1's strength property. This distinguishes properties of one instance from another, especially in interactions between objects like the attack method.

Examples of TypeScript Classes, Properties, and Methods

To deepen our understanding of TypeScript classes, let's explore another example where we build a basic BankAccount class. This class will demonstrate how we can model real-world entities using object-oriented programming by defining properties with type annotations like the account holder's name and balance, and methods for depositing and withdrawing money.

TypeScript
1// Define the BankAccount class 2class BankAccount { 3 // Constructor with a default balance of 0, utilizing type annotations 4 constructor(public holderName: string, public balance: number = 0) {} 5 6 // Method to deposit money with type annotation 7 deposit(amount: number): void { 8 if (amount > 0) { 9 this.balance += amount; 10 console.log(`${amount} deposited. New balance: ${this.balance}`); 11 } else { 12 console.log("Deposit amount must be positive."); 13 } 14 } 15 16 // Method to withdraw money with type annotation 17 withdraw(amount: number): void { 18 if (0 < amount && amount <= this.balance) { 19 this.balance -= amount; 20 console.log(`${amount} withdrawn. Remaining balance: ${this.balance}`); 21 } else { 22 console.log("Insufficient balance for the withdrawal or amount is not positive."); 23 } 24 } 25} 26 27// Create an instance of BankAccount 28const account = new BankAccount("Alex", 1000); // An account with initial balance of 1000 29 30// Perform some transactions 31account.deposit(500); // Deposit money 32// Output: 500 deposited. New balance: 1500 33 34account.withdraw(200); // Withdraw money 35// Output: 200 withdrawn. Remaining balance: 1300 36 37console.log(`Final balance in ${account.holderName}'s account: ${account.balance}`); 38// Output: Final balance in Alex's account: 1300

This example further illustrates how classes effectively encapsulate data (properties) and functionalities (methods), enabling us to mimic real-life scenarios. Here, the BankAccount class allows the creation of objects representing bank accounts, emphasizing the powerful organizational benefits of using classes in TypeScript by leveraging static typing.

Lesson Summary and Practice

Great work exploring TypeScript classes, their properties, and methods. TypeScript classes help organize your code, improving its readability, manageability, and reliability with static typing. Now, test your understanding with exercise problems to solidify your newly gained knowledge. Happy coding!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.