Classes
A class defines a custom type with fields (data) and methods (behavior). This page covers defining and using classes; the rest of this section goes deeper: Encapsulation & Accessors for access control, Static Members for class-level state, and Inheritance for subclassing.
Defining a class
Declare fields with a type, then create instances with new:
class Rectangle { public width: f64; public height: f64;}
let rect: Rectangle = new Rectangle();rect.width = 10.0;rect.height = 5.0;Constructors
A constructor initializes an object’s fields. It runs automatically when you write
new ClassName(...):
class Point { public x: i32; public y: i32;
constructor(x: i32, y: i32) { this.x = x; this.y = y; }}
let p: Point = new Point(10, 20);console.log(p.x + p.y); // 30Methods
Methods are functions attached to a class that operate on the instance:
class Rectangle { public width: f64; public height: f64;
constructor(w: f64, h: f64) { this.width = w; this.height = h; }
public area(): f64 { return this.width * this.height; }
public perimeter(): f64 { return 2.0 * (this.width + this.height); }}
let rect: Rectangle = new Rectangle(10.0, 5.0);let a: f64 = rect.area(); // 50.0let p: f64 = rect.perimeter(); // 30.0Methods can take rest parameters — prefix the final
parameter with ...:
class Accumulator { public base: i32;
constructor(base: i32) { this.base = base; }
public sum(...nums: i32[]): i32 { let total: i32 = this.base; for (let i: i32 = 0; i < nums.length; i++) { total += nums[i]; } return total; }}
let acc: Accumulator = new Accumulator(10);let total: i32 = acc.sum(1, 2, 3); // 16String representation
Every value can be turned into a string, so console.log, string concatenation, and template strings
work on any object out of the box. By default an object prints structurally (ClassName { field: value }). Define a public toString(): string to customize it — it’s used everywhere the object
becomes a string, including nested inside other objects:
class Temperature { celsius: f64; constructor(celsius: f64) { this.celsius = celsius; } toString(): string { return this.celsius + "°C"; }}
let t: Temperature = new Temperature(21.5);console.log(t); // 21.5°Cconsole.log("now: " + t); // now: 21.5°CSee Console for the full details of how values render.
The this keyword
Inside a method, this refers to the current instance — use it to read and update the object’s own
fields:
class Counter { public value: i32;
constructor(start: i32) { this.value = start; }
public increment(): void { this.value = this.value + 1; }
public getValue(): i32 { return this.value; }}
let c: Counter = new Counter(41);c.increment();console.log(c.getValue()); // 42Object references
Objects are passed by reference. A function that mutates its parameter changes the caller’s object:
class Box { public value: i32; constructor(v: i32) { this.value = v; }}
function modifyBox(box: Box): void { box.value = 999;}
let myBox: Box = new Box(10);modifyBox(myBox);console.log(myBox.value); // 999Nested objects
A field can hold another object, letting you compose larger structures:
class Point { public x: i32; public y: i32; constructor(x: i32, y: i32) { this.x = x; this.y = y; }}
class Line { public start: Point; public end: Point;
constructor(p1: Point, p2: Point) { this.start = p1; this.end = p2; }
public length(): i32 { let dx: i32 = this.end.x - this.start.x; let dy: i32 = this.end.y - this.start.y; return dx + dy; // Manhattan distance }}
let line: Line = new Line(new Point(0, 0), new Point(10, 20));console.log(line.length()); // 30Null and null-safety
An object variable can be null, either explicitly or when left uninitialized:
class Node { public value: i32; public next: Node;
constructor(v: i32) { this.value = v; this.next = null; // no next node yet }}Zeus checks for null on every property access. Reaching through a null reference throws a
NullReferenceException:
let person: Person; // null by defaultconsole.log(person.name); // throws NullReferenceExceptionfunction getName(person: Person): string { try { return person.name; } catch (e: Error) { return "Unknown"; }}Classes with arrays
A field can be an array. Initialize it in the constructor, then use the array methods:
class Team { public scores: i32[];
constructor() { this.scores = new i32[]; }
public addScore(score: i32): void { this.scores.push(score); }
public getScore(index: i32): i32 { return this.scores.get(index); }}
let team: Team = new Team();team.addScore(10);team.addScore(20);team.addScore(30);console.log(team.getScore(1)); // 20Anonymous classes
A class expression creates a type inline, without a top-level declaration — handy for one-off objects.
Assign it to a const and use that name as the type:
const Counter = class { public n: i32; constructor(start: i32) { this.n = start; }
inc(): i32 { this.n = this.n + 1; return this.n; }}
let c = new Counter(9);console.log(c.inc()); // 10You can also give the expression an internal name — both the variable and the class name are then usable:
const Vec = class Vector { public x: i32; public y: i32; constructor(x: i32, y: i32) { this.x = x; this.y = y; } sum(): i32 { return this.x + this.y; }}
let a = new Vec(3, 4); // via the constlet b = new Vector(1, 2); // via the class nameconsole.log(a.sum() + b.sum()); // 10Or define and instantiate in a single expression — the class equivalent of an IIFE:
let obj = new (class { public v: i32; constructor(v: i32) { this.v = v; } get(): i32 { return this.v; }})(42);
console.log(obj.get()); // 42