Classes with Types¶
TypeScript adds structure, safety, and clarity to JavaScript’s class syntax. You get:
- typed fields
- typed constructors
- visibility modifiers
- abstract classes
- parameter properties
- strict initialization checks
Let’s break these down.
Access Modifiers¶
TypeScript adds three visibility modifiers to class members:
public— accessible everywhere (default)private— accessible only inside the classprotected— accessible inside the class and subclasses
These modifiers exist only at compile time—they do not change JavaScript’s runtime behavior.
Public (default)¶
class User {
public name: string
constructor(name: string) {
this.name = name
}
}
const u = new User("Alice")
console.log(u.name) // ✔ OK
You can omit public because it’s the default.
Private¶
class BankAccount {
private balance: number = 0
deposit(amount: number) {
this.balance += amount
}
}
const acc = new BankAccount()
acc.deposit(100)
acc.balance // ❌ Error: private
Private members enforce encapsulation and prevent accidental misuse.
Protected¶
class Animal {
protected move() {
console.log("Moving...")
}
}
class Dog extends Animal {
bark() {
this.move() // ✔ OK (protected)
}
}
const d = new Dog()
d.move() // ❌ Error: protected
Protected is perfect for template methods and inheritance patterns.
Parameter Properties¶
Parameter properties are a TypeScript feature that reduces boilerplate in constructors.
Instead of writing:
class User {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
}
You can write:
class User {
constructor(
public name: string,
public age: number
) {}
}
This:
- declares the fields
- assigns them
- applies access modifiers
All in one place.
Supported modifiers¶
publicprivateprotectedreadonly
Example with readonly¶
class Point {
constructor(
public readonly x: number,
public readonly y: number
) {}
}
const p = new Point(10, 20)
p.x = 5 // ❌ Error: readonly
Parameter properties are extremely common in idiomatic TypeScript.
Abstract Classes¶
Abstract classes define a base class that cannot be instantiated directly.
They are used to enforce structure in subclasses.
Basic abstract class¶
abstract class Shape {
abstract area(): number
describe() {
return `Area: ${this.area()}`
}
}
Subclass must implement abstract methods¶
class Circle extends Shape {
constructor(public radius: number) {
super()
}
area() {
return Math.PI * this.radius ** 2
}
}
const c = new Circle(10)
console.log(c.describe()) // Works
Trying to instantiate the abstract class:
new Shape() // ❌ Error
Why abstract classes matter¶
- enforce consistent APIs across subclasses
- provide shared logic + required overrides
- ideal for frameworks, engines, and domain models
Classes + Interfaces¶
Classes can implement interfaces to enforce structure.
interface Serializable {
serialize(): string
}
class User implements Serializable {
constructor(public name: string) {}
serialize() {
return JSON.stringify({ name: this.name })
}
}
This ensures the class provides the required methods.
Putting It All Together¶
Here’s a realistic example combining access modifiers, parameter properties, and abstract classes:
abstract class Repository<T> {
protected items: T[] = []
add(item: T) {
this.items.push(item)
}
abstract findById(id: string): T | undefined
}
interface Entity {
id: string
name: string
}
class UserRepository extends Repository<Entity> {
findById(id: string) {
return this.items.find(item => item.id === id)
}
}
const repo = new UserRepository()
repo.add({ id: "1", name: "Alice" })
console.log(repo.findById("1"))
This example demonstrates:
- abstract base class
- protected fields
- generics
- interface implementation
- concrete subclass behavior
This is the foundation of OOP in TypeScript.
Summary¶
In this lesson, you learned how TypeScript enhances classes with:
1. Access modifiers¶
public,private,protected- compile‑time visibility enforcement
2. Parameter properties¶
- concise constructor syntax
- automatic field declaration + assignment
- supports
readonly
3. Abstract classes¶
- enforce required methods
- provide shared logic
- cannot be instantiated directly
These features make TypeScript’s class system far more expressive and safer than plain JavaScript, while staying fully compatible with JavaScript’s runtime model.