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 ‘#‘”.