TypeScript constructor parameter properties

TypeScript offers a short-cut to creating properties/fields from the parameters declared on the constructor.

For example, if we declare our class and constructor like this

class Person {
    constructor(name: string, age: number) {
    }
}

let p = new Person("Scooby", 10);
p.name = "Doo";

The TypeScript transpiler will display the error “Property ‘name’ does not exist on type ‘Person'” and obviously the parameters name and age will not exist within the Person class as they’ve not been declared.

However if we prefix the parameters with either public, private, protected or readonly then TypeScript generates properties on the Person object automatically for us.

protected parameter properties

As you’d probably expect, with the accessor of protected properties are generated which are visible to the Person object and any subclass of the Person.

For example

class Person {
    constructor(protected name: string, protected age: number) {
    }
}

When we run this through the transpiler we get the following

var Person = /** @class */ (function () {
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    return Person;
}());

If we attempt to access the properties name and age from outside the class (using TypeScript) then we’ll get the error “Property ‘name’ is protected and only accessible within class ‘Person’ and its subclasses.”.

private parameter properties

If we now change the accessors to private, for example

class Person {
    constructor(private name: string, private age: number) {
    }
}

The transpiler will, again, create the same output as the previous JavaScript code, but the generated properties, from the TypeScript point of view, are only accessible from the Person class. Trying to access them from outside of the Person class will result in the following error, “Property ‘name’ is private and only accessible within class ‘Person’..

public parameter properties

Changing the accessors to public will, as you probably expected, create public properties/fields which are accessible outside of the Person class, here’s the altered source code.

class Person {
    constructor(public name: string, public age: number) {
    }
}

Ofcourse, the JavaScript code is unchanged.

readonly parameter properties

Finally, if we now change the accessors to readonly, for example

class Person {
    constructor(readonly name: string, readonly age: number) {
    }
}

The transpiler will generate, what appears to be, getters only. Hence trying to interact with these properties outside of the class will result in the following error “Cannot assign to ‘name’ because it is a read-only property.”

Whilst JavaScript can support the concept of readonly properties, the transpiler does not go this route (shown below)

Readonly properties in JavaScript

If we take the code generated by the transpiler, we could add the following

Object.defineProperty(Person.prototype, "name", {
    value: "name",
    writable: false
});

and when run (assuming we try to assign a value to name), we’ll get the following error “Cannot assign to read only property ‘name’ of object ‘#‘”.