Properties and fields in TypeScript

There’s several ways to handle properties within TypeScript, let’s look at a simple class

class Point {
    x: number;
    y: number;
}

Whilst Visual Code etc. will say these are properties, they’re more like public fields (if you wish to compare to a language such as C#), hence missing the functional side that comes with properties.

By default no accessors means the properties x and y are public. TypeScript allows us to mark them as private in which case we could then write functional getters and setters as per Java, for example

class Point {
    private x: number;
    private y: number;

    getX() {
        return this.x;
    }
    setX(x: number) {
        this.x = x;
    }
    getY() {
        return this.y;
    }
    setY(y: number) {
        this.y = y;
    }
}

TypeScript also supports C# style property getter and setters like this

class Point {
    private x: number;
    private y: number;

    get X() : number {
        return this.x;
    }
    set X(x : number) {
        this.x = x;
    }
    get Y() : number {
        return this.y;
    }
    set Y(y : number) {
        this.y = y;
    }
}

and like C# these get/set methods result in property style syntax, i.e.

var p = new Point();
p.Y = 4;
console.log(p.Y);

Constructors within TypeScript can reduce the ceremony for creating fields and properties by using the private or public keywords for constructor arguments, for example

class Point {
  constructor(public x: number, public y: number) {
  }
}

// becomes

class Point {
    get x() {
        return this.x;
    }
    set x(x) {
        this.x = x;
    }
    get y() {
        return this.y;
    }
    set y(y) {
        this.y = y;
    }
}

Using private constructor arguments is equivalent private fields, so for example

class Point {
  constructor(private x: number, private y: number) {
  }
}

// becomes

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
}

If we need to overwrite the getter/setters functionality, we can write

class Point {
    constructor(public x: number, public y: number) {
    }
   
    public get x() : number {
        return this.x;
    }
    public set x(x : number) {
        this.x = x;
    }   
    public get y() : number {
        return this.x;
    }
    public set y(y : number) {
        this.y = y;
    }
}