Skip to content

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 ​

ModifierVisible from
publicEverywhere (the default)
protectedThe class and its subclasses
privateThe 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 ​

  • #private fields. Use private.
  • Static initializer blocks. Use static fields with initializers.
  • Multiple inheritance. Use interfaces and composition.