Encapsulation in TypeScript
Lonv'ha KPETO
Posted on April 21, 2022
TypeScript(TS) developers usualy use encapsulation bad. This is due to the fact that they just learned it in the context of building angular, React and even Vue JS like applications. Their focus was not primarily TS but other thing.
This guide is for web developers who wish to understand the basic of property encapsulation in TS. At the end, you will:
- Know what property encapsulation is;
- Know non-encapsulation bottlenecks;
- Hide properties with encapsulation;
- Enhance class definition with encapsulation.
To be able to follow allong correctly, we suppose you know the following concepts:
- Classes definition and motivation;
- Variable declaration;
- Object oriented concepts like classes, objects, polymorphisms, abstract classes, etc.
What are variables ?
A variable is a memory reservation in order to store values. For the computer to know what calculations it can make on variables, they need to have types. A type is a definition of a set of values and the operations that can be applied to them. For exemple, if we decide to dim a variable as an integer, the implication is that it can be able to store all integer values and they can participate to addition, substraction, mutiplication and many more operations. This makes sens. However, if we decide to dim a variable as a string, it can surely store all kind of texts but what about adding two string? We can say it's concatenation (adding one string at the end of another one). What about subtracting two strings? It is not semantic. So are some operations like multiplication and division.
Langages in the world fall in two categories: typed and untyped. Typed langages enforce you to specifiy the type of a variable at it declaration. This have many benefits:
- It helps build quality software,
- It helps detect some compile time issues,
- It lowers the bug atractivity of a computer program.
TS is a typed language. This means every variable in TS is supposed to have a type. There are some basic types like number, string, boolean. For exemple, the following code declares a variable named numberOfPeople of type number that can receive numbers and participate to all number friendly operations.
let numberOfPeople: number = 7;
Basically, you can declare a variable of any type. It can be basic types or even complex programmer defined types like classes and interfaces.
let albert: Personne = undefined;
Class declaration in typescript
The basic class definition in TS is like the following.
class Person {}
This declares a class (a new type) named Person. With this assert, we can declare variables like what follows.
let joe: Person = new Person();
Classes can have properties and methods as well. They all form the body of a class definition. Properties describe the characteristics of the class. Methods describe the behavior.
class Person {
name: String; // A characteristic of a person
run(): String { // A behavior of the Person
return `${this.name} is running fast.`;
}
}
Properties and methods in a class can have access modifiers to specify the scope of availability. Access modifiers are tools to realize encapsulation. A private access specifier intends visibility only inside of the class. A public available everywhere and a protected is only available in the class and all it's sub-classes (classes extending a class to add more functionality).
The substance of encapsulation is using access modifiers to restrict unwanted access and protect data from side effects. Let's say we want to design a User class so that it encapsulates a password property. We can come up first with something like the following exemple.
export class User {
password: string;
getPassword(): string {
return this.password;
}
setPassword(password: string): void {
this.password = password;
}
}
Then we can refactor it to something more interesting.
export class User {
_password: string;
constructor(_password: string) {
this._password = _password;
}
get password(): string {
return this._password;
}
set password(password: string) {
this._password = password;
}
givePass(): string {
return `I don't want to do that outside of this class`;
}
}
By default in TS, all class properties and methods are public. A huge misconception about that fact is that properties starting with and underscore (_) are private. It is not the case. I think it's just a convention of doing things to start naming private properties with and underscore. Let's prove that by testing the class. Just add the following lines to the previous file.
let robert: User = new User('Robert');
console.log(robert.password); // => Robert
console.log(robert._password); // Works but should throw exception
Let me show you what I got as response.
The output shows that I am still able to see and even update the property I thought was encapsulated.
To fix this issue, we need to strictly specify the access modifier.
export class User {
private _password: string;
constructor(_password: string) {
this._password = _password;
}
get password(): string {
return this._password;
}
set password(password: string) {
this._password = password;
}
givePass(): string {
return `I don't want to do that outside of this class`;
}
}
If you run the test code back again, you will get the following output.
Tada! That's what we are looking for: restricting access to properties and methods so that they are only accessible where we want them for the purpose of protecting data.
Give aways
To strictly encapsulate in TS, you can follow the following steps:
find the way to define the property or method and mark it with the good access modifier (You can use the underscore private variable naming strategy);
provide getters and setters to control the access mecanism of the property if needed;
enjoy seeing encapsulation working for you!
Posted on April 21, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.