Lab 04: Classes & OOP
Objective
Build TypeScript classes with access modifiers, abstract classes, readonly, static members, parameter properties, and proper OOP patterns.
Background
TypeScript classes extend JavaScript's ES2015 classes with type annotations and access modifiers (private, protected, public). TypeScript's private is checked at compile time; JavaScript's #private (also supported) is enforced at runtime. TypeScript classes compile to regular JavaScript constructor functions.
Time
35 minutes
Prerequisites
Lab 01–03
Tools
Docker image:
zchencow/innozverse-ts:latest
Lab Instructions
Step 1: Class Basics & Parameter Properties
💡 Parameter properties (
private readonly accountId: string) declare AND assign properties in the constructor — no need to writethis.accountId = accountIdmanually. This is a TypeScript-only feature that reduces boilerplate significantly, especially for DTOs and value objects.
📸 Verified Output:
Step 2: Inheritance & Protected Members
💡
protectedmembers are accessible within the class AND its subclasses, but not from outside. Useprotectedfor properties/methods that subclasses need to override behavior.privatemeans truly internal — even subclasses can't access it. TypeScript's access modifiers are compile-time only (unlike#private).
📸 Verified Output:
Step 3: Static Members & Factory Methods
💡 Private constructor + static factory methods is the Named Constructor pattern —
Color.fromHex()is clearer thannew Color()with hex parsing inside. It also prevents subclassing (you can't callsuper()if the constructor is private to the parent). Use it for value objects and singletons.
📸 Verified Output:
Step 4: Interfaces + implements
💡
implementsvsextends:extendsinherits code from a parent class;implementsonly checks that your class has the required shape — no code is inherited. A class can implement multiple interfaces but only extend one class. Think of interfaces as contracts and classes as implementations.
📸 Verified Output:
Step 5: Mixins
💡 Mixins add capabilities without inheritance hierarchies.
Timestamped(User)wraps User in a new anonymous class that adds timestamp properties. CombiningTimestamped,Activatable, andSerializablegives you a class with all three features. This is how Angular's@Injectable()decorator works internally.
📸 Verified Output:
Step 6: Generic Classes
💡 Generic classes carry the type parameter through all methods.
Stack<number>creates a stack wherepushonly accepts numbers andpopreturnsnumber | undefined. The type is resolved at instantiation — one class definition, infinite type-safe variants.
📸 Verified Output:
Step 7: Abstract Classes & Template Method
📸 Verified Output:
Step 8: Complete — Entity Framework Pattern
💡
BaseEntity.nextId++is a class-level counter — static properties are shared across all instances. Each subclass that callssuper()gets a unique ID. In production, IDs come from databases; in tests, this auto-increment pattern avoids external dependencies.
📸 Verified Output:
Summary
TypeScript OOP is powerful and expressive. You've covered parameter properties, inheritance, abstract classes, implements, static members, mixins, generic classes, the Template Method pattern, and an entity framework. These patterns power Angular, NestJS, TypeORM, and every TypeScript-first backend.
Further Reading
Last updated
