Chapter 5 of 13
~13 minClasses & OOP in TypeScript
TypeScript extends JavaScript's classes with typed fields, access modifiers, and abstract classes, giving you the vocabulary of traditional object-oriented programming while still compiling down to the same class syntax JavaScript already runs.
Typed Class Fields
A class field can be annotated the same way a variable can - `name: string` - and, with strict mode's `strictPropertyInitialization` enabled, the compiler requires every field to be assigned either at declaration, in the constructor, or explicitly marked optional (`age?: number`) or definitely-assigned (`age!: number`), so you cannot accidentally leave a required field uninitialized.
Try it yourself
class Product { name: string; price: number; inStock: boolean = true; // field with a default value constructor(name: string, price: number) { this.name = name; this.price = price; } } const item = new Product('Keyboard', 49.99); console.log(item.name, item.price, item.inStock);
No output yet. Use console.log() to print values here.
Access Modifiers: public, private, protected
`public` (the default when nothing is written) means a member is reachable from anywhere. `private` restricts access to inside the declaring class only - not even subclasses can reach it. `protected` allows access from the declaring class and any subclass, but not from outside code. These are compile-time-only restrictions in standard TypeScript output (unless you use the newer `#privateField` JavaScript syntax, which is enforced at runtime too).
Try it yourself
class BankAccount { public accountHolder: string; private balance: number; protected accountNumber: string; constructor(accountHolder: string, accountNumber: string, initialBalance: number) { this.accountHolder = accountHolder; this.accountNumber = accountNumber; this.balance = initialBalance; } deposit(amount: number): void { this.balance += amount; // OK - private is accessible within this class } getBalance(): number { return this.balance; } } const account = new BankAccount('Ada', 'ACC-001', 100); account.deposit(50); console.log(account.getBalance()); // 150 // console.log(account.balance); // Error: 'balance' is private
No output yet. Use console.log() to print values here.
Constructor Parameter Properties
TypeScript offers a shorthand where prefixing a constructor parameter with an access modifier (`public`, `private`, `protected`, or `readonly`) both declares the field and assigns it from the argument, without needing a separate field declaration plus a `this.x = x` assignment. This removes a lot of the boilerplate that classes otherwise accumulate.
Try it yourself
class Point { constructor( public readonly x: number, public readonly y: number, ) {} } const p = new Point(3, 4); console.log(p.x, p.y); // 3 4 // p.x = 10; // Error: x is readonly
No output yet. Use console.log() to print values here.
implements and Abstract Classes
A class can declare `implements SomeInterface` to have the compiler verify it provides every member that interface requires - `implements` is purely a compile-time contract check and adds no runtime behavior of its own. An `abstract class`, by contrast, can provide real shared implementation plus one or more `abstract` methods that have no body and must be implemented by any concrete subclass; an abstract class itself can never be instantiated directly with `new`.
Try it yourself
interface Shape {
area(): number;
}
abstract class BaseShape implements Shape {
abstract area(): number;
describe(): string {
return `This shape has an area of ${this.area()}`;
}
}
class Circle extends BaseShape {
constructor(private radius: number) {
super();
}
area(): number {
return Math.PI * this.radius ** 2;
}
}
const circle = new Circle(2);
console.log(circle.describe());
// new BaseShape(); // Error: cannot create an instance of an abstract class
No output yet. Use console.log() to print values here.
Coding challenge
Create an abstract class Employee with a protected name: string (assigned via constructor parameter property) and an abstract method calculatePay(): number. Extend it with a SalariedEmployee class that stores a monthly salary and implements calculatePay to return that salary.
// Write your solution here
No output yet. Use console.log() to print values here.
Answer every question below to mark this chapter as complete.
Quiz Yourself
Score: 0/51. What is the difference between `private` and `protected` members in a TypeScript class?
2. What does the constructor parameter property shorthand `constructor(private name: string) {}` do?
3. Can an abstract class be instantiated directly with `new`?
4. What does a class declaring `implements Shape` actually enforce?
5. With `strictPropertyInitialization` enabled, what must be true of a required class field with no default value?