Building with Classes
Create reusable blueprints for real-world objects. Combine data and behavior, control access to properties, and extend classes to build more capable programs.
class Developer {
name: string;
level: number;
constructor(name: string) {
this.name = name;
this.level = 8;
}
greet() {
return "Hello, " + this.name;
}
}
const moe = new Developer("Moe");
Create Blueprints for Objects
In the previous lesson, you learned that an interface describes the structure an object should follow. A class goes further: it provides the actual code for creating objects, including their properties and methods.
Imagine you’re building a website that tracks developer profiles. Instead of writing every profile object from scratch, you can define a class and create as many developers as you need.
class Developer {
name: string = "Moe";
level: number = 8;
}
const moe = new Developer();
console.log(moe.name);
console.log(moe.level);The class keyword creates the blueprint. The new keyword creates an individual object, called an instance, from that blueprint.
Customize Objects When You Create Them
A constructor runs automatically when you create an instance using new. It lets you provide different starting values for each object.
class Developer {
name: string;
level: number;
constructor(name: string, level: number) {
this.name = name;
this.level = level;
}
}
const moe = new Developer("Moe", 8);
const jordan = new Developer("Jordan", 5);
console.log(moe.name);
console.log(jordan.level);Each instance gets its own property values. The keyword this refers to the current instance, so this.name means the name property of that particular object.
Give Your Objects Something to Do
Properties describe an object. Methods define actions that the object can perform.
class Developer {
constructor(public name: string) {}
greet(): void {
console.log("Hello from " + this.name);
}
}
const moe = new Developer("Moe");
moe.greet();Notice public name: string in the constructor. This is a TypeScript parameter property: it declares and initializes the property without needing a separate assignment.
Control Access to Properties
TypeScript provides access modifiers that describe where class members can be accessed.
class Developer {
public name: string;
private points: number;
constructor(name: string) {
this.name = name;
this.points = 0;
}
addPoints(amount: number): void {
this.points += amount;
}
showPoints(): void {
console.log(this.points);
}
}
const moe = new Developer("Moe");
moe.addPoints(25);
moe.showPoints();
// TypeScript error:
// console.log(moe.points);public members can be accessed from outside the class. private members can only be accessed from within the declaring class.
private modifier is enforced by the type checker. JavaScript’s #privateField syntax provides runtime-enforced privacy.Protect Values After Initialization
A readonly property can be assigned when declared or inside the constructor, but cannot be reassigned afterward through normal TypeScript code.
class Developer {
readonly id: number;
name: string;
constructor(id: number, name: string) {
this.id = id;
this.name = name;
}
}
const moe = new Developer(108, "Moe");
moe.name = "Moe M.";
// TypeScript error:
// moe.id = 200;Readonly properties are useful for identifiers and other values that should stay consistent after an object is created.
Control How Values Are Read and Updated
Getters and setters let a class expose a property-like interface while controlling how a value is accessed or changed.
class Developer {
private _level: number = 1;
get level(): number {
return this._level;
}
set level(value: number) {
if (value > 0) {
this._level = value;
}
}
}
const moe = new Developer();
moe.level = 8;
console.log(moe.level);The setter checks that the new level is positive before saving it. The getter returns the current value.
Build New Classes from Existing Ones
Inheritance lets one class reuse and extend the behavior of another. Use extends to create a subclass.
class Person {
constructor(public name: string) {}
greet(): void {
console.log("Hello, I'm " + this.name);
}
}
class Developer extends Person {
constructor(
name: string,
public language: string
) {
super(name);
}
}
const moe = new Developer("Moe", "TypeScript");
moe.greet();
console.log(moe.language);The Developer class inherits name and greet() from Person. The super(name) call runs the parent class’s constructor.
Customize Inherited Behavior
A subclass can provide its own implementation of a method inherited from its parent class. TypeScript’s override keyword makes that intention explicit.
class Person {
greet(): void {
console.log("Hello!");
}
}
class Developer extends Person {
override greet(): void {
console.log("Hello from a developer!");
}
}
const moe = new Developer();
moe.greet();The subclass replaces the inherited implementation with its own behavior. The method still needs a compatible signature.
Connect Classes to Your Type Contracts
Classes and interfaces work together. A class can use implements to promise that it provides the properties and methods required by an interface.
interface Profile {
name: string;
introduce(): void;
}
class Developer implements Profile {
constructor(public name: string) {}
introduce(): void {
console.log("Developer: " + this.name);
}
}
const moe = new Developer("Moe");
moe.introduce();The interface checks the class’s public structure, while the class provides the working implementation.
Build a Developer Progress Tracker
Let’s create a developer class that stores a name, tracks a level, and allows progress through a method.
class Developer {
constructor(
public name: string,
private level: number
) {}
levelUp(): void {
this.level++;
}
showProfile(): void {
console.log("Developer: " + this.name);
console.log("Level: " + this.level);
}
}
const moe = new Developer("Moe", 7);
moe.levelUp();
moe.showProfile();With a single class, you now have a reusable way to create developer profiles and update their progress.
Create Your Developer Progress Tracker
Build a reusable class that tracks a developer’s learning journey.
Your Mission
- Create a class named
Developer. - Use a constructor to accept a developer’s name and starting level.
- Make the name public and the level private.
- Add a
levelUp()method that increases the level by one. - Add a
showProfile()method that prints the developer’s name and level. - Create a developer named Moe, call
levelUp(), and display the updated profile. - Experiment with changing the level directly from outside the class and examine the TypeScript error.
readonly id property and a getter that returns the current level.Build Your Developer Class!
Edit the class, create developer instances, and run the program. TypeScript checks your code before the compiled JavaScript runs.
Preparing TypeScript sandbox…
What You’ve Learned
You’re Building Reusable Programs!
You can now:
- Define classes and create instances with
new. - Initialize properties using constructors.
- Create methods that work with instance data.
- Use
public,private, andreadonly. - Control property access using getters and setters.
- Extend classes using inheritance.
- Override inherited methods.
- Implement interfaces with classes.
Next up: Generics — learn how to write reusable TypeScript code that works with multiple types while preserving type safety!
Your Learning Journey
0 / 11 CompletedYou’re eight lessons into your TypeScript journey. Keep building!
You’re Mastering TypeScript!
You’ve learned how to create classes, initialize objects with constructors, define methods, control property access, and extend classes. You’re now building reusable code with object-oriented programming!
