Classes
A class
ts
class Enemy {
name: string;
hp: int;
constructor(name: string, hp: int) {
this.name = name;
this.hp = hp;
}
hit(damage: int): void {
this.hp -= damage;
if (this.hp < 0) {
this.hp = 0;
}
}
isDefeated(): boolean {
return this.hp == 0;
}
}
const slime: Enemy = new Enemy("Slime", 10);
slime.hit(4);
console.log(slime.name, slime.hp, slime.isDefeated());Methods do not use the function keyword. Writing function hit() inside a class is a syntax error.
Field defaults
When every field has a default and there is no constructor, one is made for you:
ts
class Settings {
volume: float = 0.8;
fullscreen: boolean = false;
language: string = "en";
}
const settings: Settings = new Settings();
console.log(settings.volume, settings.language);Constructor parameter properties
Put public, private, protected or readonly (alone or after an access modifier) on a constructor parameter to declare the field and assign it in one step:
ts
class Point {
constructor(public x: int, public y: int) {}
}
const p: Point = new Point(3, 4);
console.log(p.x, p.y);Access modifiers and readonly
| Modifier | Visible from |
|---|---|
public | Everywhere (the default) |
protected | The class and its subclasses |
private | The class only |
readonly fields can only be set in the constructor. The checker enforces all of these.
ts
class Wallet {
readonly owner: string;
private coins: int = 0;
constructor(owner: string) {
this.owner = owner;
}
add(amount: int): void {
this.coins += amount;
}
get balance(): int {
return this.coins;
}
}
const w: Wallet = new Wallet("Ada");
w.add(25);
console.log(w.owner, w.balance);Getters and setters
get and set define properties that run code. They are read and written like fields:
ts
class Temperature {
private celsius: float = 0;
get fahrenheit(): float {
return this.celsius * 1.8 + 32;
}
set fahrenheit(value: float) {
this.celsius = (value - 32) / 1.8;
}
}
const t: Temperature = new Temperature();
t.fahrenheit = 212;
console.log(t.fahrenheit);Static members and constants
ts
class Limits {
static const MAX_PARTY: int = 4;
static created: int = 0;
static track(): void {
Limits.created += 1;
}
}
Limits.track();
console.log(Limits.MAX_PARTY, Limits.created);static const is the preferred way to write a class constant. Statics are reached through the class name, not an instance. A subclass inherits its parent's statics.
Inheritance
A class extends one parent. A subclass constructor must call super() before it touches this:
ts
class Animal {
constructor(public name: string) {}
speak(): string {
return this.name + " makes a sound";
}
}
class Dog extends Animal {
tricks: int;
constructor(name: string, tricks: int) {
super(name);
this.tricks = tricks;
}
override speak(): string {
return this.name + " barks";
}
}
const rex: Animal = new Dog("Rex", 3);
console.log(rex.speak());
console.log(rex instanceof Dog);override is optional, but the checker then makes sure the parent really has that method. super.speak() calls the parent's version.
Abstract classes
An abstract class cannot be created directly. Subclasses must implement its abstract methods:
ts
abstract class Shape {
abstract area(): float;
describe(): string {
return "area " + this.area();
}
}
class Circle extends Shape {
constructor(public radius: float) {
super();
}
area(): float {
return Math.PI * this.radius * this.radius;
}
}
const c: Circle = new Circle(2);
console.log(c.describe());Final
final class cannot be extended. A final method cannot be overridden.
ts
final class Token {
value: string = "";
}
class Base {
final id(): string {
return "base";
}
}
console.log(new Token().value.length, new Base().id());Custom toString
A toString() method is used whenever the object becomes a string:
ts
class Rgb {
constructor(public r: int, public g: int, public b: int) {}
toString(): string {
return `rgb(${this.r}, ${this.g}, ${this.b})`;
}
}
console.log(String(new Rgb(255, 128, 0)));Not supported
#privatefields. Useprivate.- Static initializer blocks. Use static fields with initializers.
- Multiple inheritance. Use interfaces and composition.