Classes, Access Modifiers & implements
Quick Overview
`private` is erased at compile time; the field is still reachable from plain JavaScript at runtime. `#name` is the version the engine actually enforces, which is the difference worth knowing.
Deep Dive
1. Object-Oriented TypeScript
TypeScript enhances ES6 classes with explicit property type annotations, access modifiers, parameter property shortcuts, and interface implementation checks.
2. Access Modifiers
public(Default): Accessible from anywhere.private: Accessible ONLY inside the defining class.protected: Accessible inside the defining class AND child subclasses.
class BankAccount {
public readonly accountId: string;
private balance: number; // Private encapsulated state
constructor(accountId: string, initialDeposit: number) {
this.accountId = accountId;
this.balance = initialDeposit;
}
public deposit(amount: number): number {
this.balance += amount;
return this.balance;
}
public getBalance(): number {
return this.balance;
}
}
3. Parameter Properties Shortcut
Simplify class constructors by placing access modifiers directly in constructor arguments:
// Concise Parameter Property Shortcut!
class User {
constructor(
public readonly id: number,
public username: string,
private secretHash: string
) {} // Properties automatically declared and assigned!
}
4. The implements Keyword
Enforce that a class conforms to a specific interface shape:
interface Logger {
log(message: string): void;
}
class ConsoleLogger implements Logger {
log(msg: string) {
console.log("[LOG]:", msg);
}
}
5. Common Mistakes
- Confusing TypeScript
privatewith JS Private Fields (#): TypeScriptprivateis erased at compile time! If you need true runtime privacy in raw JS, use JavaScript private fields (#balance).
6. Next Steps
Use classes for OOP domain models. Next, let's explore Abstract Classes and Polymorphism!
Next Up in TypeScript & Type System Mechanics
TypeScript Primitives & Explicit Type Annotations
TypeScript erases entirely at build time, so a `string` annotation produces no runtime check whatsoever. A value arriving from an API is whatever the server actually sent, regardless of what the annotation claims.
Type Inference & Literal Types (const vs. let)
`let x = "GET"` infers `string` because the binding can change; `const x = "GET"` infers the literal `"GET"`. That widening rule is why object properties need `as const` to stay narrow.
Arrays, Tuples & Readonly Modifiers
`string[]` is any number of strings; `[string, number]` is exactly two, in that order. `readonly` removes the mutating methods at compile time, so `push` becomes a type error rather than a runtime surprise.
