TypeScript - Classes
TypeScript - Classes
Section titled “TypeScript - Classes”Classes are a fundamental concept in object-oriented programming (OOP) and serve as blueprints for creating objects. They encapsulate data (properties or fields) and behavior (methods or functions) related to a specific entity. TypeScript provides first-class support for the class syntax introduced in ES6, enhanced with features like type annotations and access modifiers.
Defining Classes
Section titled “Defining Classes”Use the class keyword followed by the class name (typically PascalCase).
Syntax
Section titled “Syntax”class ClassName { // Fields (Properties) propertyName: type; anotherProperty?: type; // Optional property readonly readOnlyProp: type = initialValue; // Readonly property private privateField: type; protected protectedField: type; static staticProperty: type = value;
// Constructor constructor(param1: type, param2: type, ...) { // Initialization logic this.propertyName = param1; // ... }
// Methods methodName(param: type): returnType { // Method logic return value; }
private privateMethod(): void { ... } protected protectedMethod(): void { ... } static staticMethod(): void { ... }
// Getters & Setters get computedValue(): type { return this.propertyName; } set computedValue(value: type) { this.propertyName = value; }}Class definitions can include:
- Fields (Properties): Variables declared within the class scope that hold data for instances of the class. Use type annotations.
- Constructor: A special method named
constructorresponsible for creating and initializing objects created with the class. Called when you use thenewkeyword. - Methods: Functions defined within the class that define the behavior of objects.
- Access Modifiers: Keywords (
public,private,protected) that control the visibility and accessibility of class members. - Readonly Modifier: Prevents modification of a property after its initial assignment (usually in the constructor).
- Static Members: Properties or methods belonging to the class itself, not instances. Accessed via
ClassName.memberName. - Getters/Setters: Special methods that provide controlled access to object properties.
Example: Simple Class
Section titled “Example: Simple Class”class Vehicle { // Properties with default access (public) make: string; model: string; year: number; private _vin: string; // Private property convention readonly id: string;
// Static property static numberOfVehicles = 0;
constructor(make: string, model: string, year: number, vin: string) { this.make = make; this.model = model; this.year = year; this._vin = vin; this.id = `veh-${Math.random().toString(36).substr(2, 9)}`; // Assign readonly property Vehicle.numberOfVehicles++; // Increment static property }
// Method displayInfo(): void { console.log(`Vehicle: ${this.year} ${this.make} ${this.model} (ID: ${this.id})`); }
// Getter for private property get vin(): string { return this._vin; }
// Static method static getVehicleCount(): number { return Vehicle.numberOfVehicles; }}
// Accessing static memberconsole.log(`Initial vehicle count: ${Vehicle.getVehicleCount()}`); // Output: 0Creating Instances (Objects)
Section titled “Creating Instances (Objects)”Use the new keyword followed by the class name and parentheses (passing arguments to the constructor if required).
const car1 = new Vehicle("Toyota", "Camry", 2022, "123ABC456DEF");const car2 = new Vehicle("Honda", "Civic", 2021, "789GHI012JKL");
console.log(`Current vehicle count: ${Vehicle.getVehicleCount()}`); // Output: 2Accessing Members
Section titled “Accessing Members”Use the dot (.) notation on the object instance to access its public properties and methods.
console.log(car1.make); // Output: Toyotacar1.displayInfo(); // Output: Vehicle: 2022 Toyota Camry (ID: veh-...)
console.log(car2.model); // Output: Civiccar2.displayInfo(); // Output: Vehicle: 2021 Honda Civic (ID: veh-...)
// Accessing via getterconsole.log(`Car 1 VIN: ${car1.vin}`);
// car1.id = "new-id"; // Error: Cannot assign to 'id' because it is a read-only property.// console.log(car1._vin); // Error: Property '_vin' is private and only accessible within class 'Vehicle'.Access Modifiers
Section titled “Access Modifiers”public(Default): Members are accessible from anywhere.private: Members are only accessible from within the defining class itself.protected: Members are accessible within the defining class and by instances of derived (sub)classes.
Parameter Properties Shorthand
Section titled “Parameter Properties Shorthand”TypeScript offers a concise syntax to declare and initialize class members directly from constructor parameters by adding an access modifier (public, private, protected) or readonly.
class Employee { // Automatically creates and initializes 'name' and 'department' properties constructor( public readonly id: number, public name: string, private department: string ) {}
getDept(): string { // Can access private member within the class return this.department; }}
const emp1 = new Employee(101, "Alice", "Engineering");console.log(emp1.name); // Output: Aliceconsole.log(emp1.id); // Output: 101console.log(emp1.getDept()); // Output: Engineering// console.log(emp1.department); // Error: Property 'department' is private...Inheritance (extends)
Section titled “Inheritance (extends)”Classes can inherit properties and methods from a single parent class (base class or superclass) using the extends keyword. The inheriting class is called a subclass or derived class.
Derived classes inherit all public and protected members. Private members are not inherited. Constructors are not inherited, but the derived class constructor must call the parent constructor using super() if the parent has a constructor.
class Animal { constructor(public name: string) {}
move(distanceInMeters: number = 0): void { console.log(`${this.name} moved ${distanceInMeters}m.`); }}
class Dog extends Animal { // Derived constructor must call super() constructor(name: string) { super(name); // Calls the parent class (Animal) constructor }
bark(): void { console.log("Woof! Woof!"); }
// Overriding the parent method move(distanceInMeters = 5): void { console.log("Running..."); super.move(distanceInMeters); // Call the parent class's move method }}
const myDog = new Dog("Buddy");myDog.bark(); // Output: Woof! Woof!myDog.move(10); // Output: Running... // Output: Buddy moved 10m.console.log(myDog.name); // Output: Buddy (inherited from Animal)Method Overriding and super
Section titled “Method Overriding and super”Derived classes can provide their own implementation for a method inherited from the parent class (overriding). Use the super keyword to call methods from the parent class (super.methodName()) or the parent constructor (super() inside the derived constructor).
Abstract Classes
Section titled “Abstract Classes”Classes marked with abstract cannot be instantiated directly. They often serve as base classes and may contain abstract methods (methods without implementation) that must be implemented by derived classes.
abstract class Department { constructor(public name: string) {}
printName(): void { console.log(`Department name: ${this.name}`); }
abstract printMeeting(): void; // Must be implemented by derived classes}
class AccountingDepartment extends Department { constructor() { super("Accounting and Auditing"); // constructors in derived classes must call super() }
printMeeting(): void { console.log("The Accounting Department meets each Monday at 10am."); }}
// const dept = new Department("General"); // Error: Cannot create an instance of an abstract class.const accounting = new AccountingDepartment();accounting.printName();accounting.printMeeting();Classes Implementing Interfaces (implements)
Section titled “Classes Implementing Interfaces (implements)”Classes can implement one or more interfaces using the implements keyword. This enforces that the class adheres to the structure defined by the interface(s).
interface ClockInterface { currentTime: Date; setTime(d: Date): void;}
class DigitalClock implements ClockInterface { currentTime: Date = new Date();
setTime(d: Date): void { this.currentTime = d; }}
const clock = new DigitalClock();console.log(clock.currentTime);