class Pet {
name: string; // property.
}
const pet = new Pet();
pet.name = "Mittens";
console.log(pet); // returns Pet { name: 'Mittens' }.
Member properties can be public, private, or protected.
- Public members are accessible from anywhere (default).
- Private members are only accessible from within the class.
- Protected members are accessible from within the class and from classes that extend from the class.
class Pet {
private name: string;
public constructor(name: string) {
this.name = name;
}
public getName(): string {
return this.name;
}
}
const pet = new Pet("Snuggles");
console.log(pet.getName()); // since pet.name is private,
// it isn't accessible outside the class.
Shorthand: add a visibility modifier to constructor parameters to auto-create and assign properties.
class Pet {
public constructor(private name: string) {}
// name is a private member variable
public getName(): string {
return this.name;
}
}
const pet = new Pet("Snowball");
console.log(pet.getName()); // logs 'Snowball'
Prevents class members from being changed.
class Pet {
private readonly name: string;
public constructor(name: string) {
// name cannot be changed after definition,
// which must be at it's declaration or in the constructor.
this.name = name;
}
public getName(): string {
return this.name;
}
}
const pet = new Pet("Jingles");
console.log(pet.getName());
The implements key word is used to indicate that a class implements an interface to define the type a class must conform to.
interface Shape {
getArea: () => number;
}
class Rectangle implements Shape {
public constructor(
protected readonly width: number,
protected readonly height: number,
) {}
public getArea(): number {
return this.width * this.height;
}
}
const ourRectangle = new Rectangle(11, 22);
console.log(ourRectangle.getArea());
Classes can implement multiple interfaces.
A class can extend another class to inherit its members. A class can only extend one other class.
interface Shape {
getArea: () => number;
}
class Rectangle implements Shape {
public constructor(
protected readonly width: number,
protected readonly height: number,
) {}
public getArea(): number {
return this.width * this.height;
}
}
class Square extends Rectangle {
public constructor(width: number) {
super(width, width);
}
// inherited from Rectangle.
}
const ourSquare = new Square(22);
console.log(ourSquare.getArea());
When you use a class to extend another, you can override methods from the parent class by redefining them in the child class. You can also override properties.
interface Shape {
getArea: () => number;
}
class Rectangle implements Shape {
// using protected for these members allows access from classes that extend from this class, such as Square
public constructor(
protected readonly width: number,
protected readonly height: number,
) {}
public getArea(): number {
return this.width * this.height;
}
public toString(): string {
return `Rectangle[width=${this.width}, height=${this.height}]`;
}
}
class Square extends Rectangle {
public constructor(width: number) {
super(width, width);
}
// Replaces earlier toString from Rectangle
public override toString(): string {
return `Square[width=${this.width}]`;
}
}
const ourSquare = new Square(22);
console.log(ourSquare.toString());
Override keyword is optional, but it’s good practice to use it.
Can be used as a base for other classes, without having to implement or use all that classes members.
abstract class Polygon {
public abstract getArea(): number;
public toString(): string {
return `Polygon[area=${this.getArea()}]`;
}
}
class Rectangle extends Polygon {
public constructor(
protected readonly width: number,
protected readonly height: number,
) {
super();
}
public getArea(): number {
return this.width * this.height;
}
}
const ourRectangle = new Rectangle(10, 20);
console.log(ourRectangle.getArea());