Encapsulation- Object Oriented Principles in Typescript

Writing Better Typescript Applications

Raymond Johnson
7 min readFeb 2, 2019

Preface

Finding a new developer who seniors can confidently entrust handing over a part of their code base is a daunting task. Why? Because finding a new developer who can actually write great software can almost be as common as finding a four leaf clover — made up by statistics in my own head haha. Whether or not that last statement was completely fabricated or not is up for conversation down in the comment section below, but if you are a new developer with an urge to write great software, please welcome yourselves to Part One of my blog series on how to write better applications in Typescript.

How to Read

This blog series is meant to be a series of articles read in order. It is my goal to make this a compound reading source where hopefully we’ve discussed any prerequisite information in an earlier article so we can begin to add these different tools to our tool belt as we begin to fix up our existing code bases one article at a time.

My Motivation Behind This Series

What motivated me to start a series on Object Oriented Typescript was learning from my own struggles that took me years to finally truly understand. I have come to realization that being a software engineer is much more than just being a weekend programmer, tutorial watcher, and course follower. But being a true engineer means being able to take a problem find a solution and structure a framework in which that solution will be solved. And And having a good grasp on the principles of OOP will put you one step closer to being that great engineer you hope to be.

What You Can Expect To Learn

After reading this article, you can bet you’ll impress all of your CS Grad friends with your new knowledge on exactly what encapsulation is, how to properly utilize it, and why it should be no longer an option, but a requirement EVERYWHERE in your code base :)

Encapsulation is a very simple concept; it is the process of ensuring accurate protection over certain data (properties) passed back and forth between your application.

And that’s honestly it! Very simple yet a very powerful concept to keep in mind as we program. With that said, let’s hop into some source code and see how this applies in a real world example.

A Rather Simple Example

For the purposes of this blog to quickly get a grasp on this topic we’re going to implement a basic Bank Member class with only a savings account.

To start, we have a class BankMember, that takes in a starting savings account balance and a couple of methods, one to deposit funds and one to withdraw funds. Super simple so far right?

Lets jump into the index.ts file with our good ol’ friend Chuck to see how this all gets put together.

Here our friend Chuck opens an account with us and starts himself off with a very generous $3,000 cash. And he already wants to deposit more. Let’s see this script in action.

Cool! Working as planned. What about withdrawing?

Perfect! That was super quick and easy. We can create new Bank Members, deposit and withdraw. We can already go ahead go ahead and ship our code out to our bank client!

Or Can We…?

At face value, our code seems to be working perfectly. No unit tests needed here ;) But what if our client misuses our source code? Or even worse, what if our client opens up their application for use in other third party applications and they maliciously tamper with account balances. Take a look below.

Do you see the bug that we as the developers indirectly implanted into the source code? We provided no type of protection over the data present in our class, therefore anyone with access to an instance of BankMember can freely change the value of that members savingsBalance.

In the example above, Chuck should very well have been able to withdraw $1,650 because he just had a balance of $3,150. But unbeknownst to him, the banking application that he uses to handle his finances is owned by a fraudulent company that steals from all of its users. So lets see how we can become better developers and utilize encapsulation to fix this issue in just a few lines of code!

Private, Protected, Getters and Setters

The key to encapsulation is understanding how controlling member access in conjunction with getter and setter methods can be used to your advantage.

Private: private members can only be accessed within the class it was defined in. Outside clients as well as inheriting classes are unauthorized.

Protected: protected members can only be accessed within the class it was defined in as well as inheriting the super class. Outside clients are unauthorized.

Getters: this is a special type of method who’s sole purpose is to give indirect read access to client code to a private or protected member that they are otherwise prohibited from. Read-only properties are made possible when used without it’s setter counterpart.

Setters: this is a special type of method who’s sole purpose is to give indirect write access to client code to a private or protected member that they are otherwise prohibited from. Write-only properties are made possible when used without it’s getter counterpart.

Ready for some more code? Let’s see some of this jargon put to action.

Did Anyone Say Bug Free?

Now that we see the flaws of leaving our code unencapsulated and know the basic principles for implementing encapsulation, lets turn Chuck’s frown upside down ):(

Implementing Encapsulation

Do you see the changes? We made our _savingsBalance property private and prepended an underscore to it to denote its private access type. (a common convention) Then most importantly, we created a public get method which our outside clients can use for leverage within their application. Take a look at our new index.ts file where all the madness was taking place.

See how typescript is smart enough to pick up on the fact that the savingsBalance property is read-only? Do you also notice how nice typescript is for throwing an error before compile time? I guess they wouldn’t want the fraudulent Banking Company to waste their time compiling code that wouldn’t work, huh? :/

A Quick Note on Getters and Setters in Typescript

In contrast to some other languages, although we define getters and setters as methods within our class, we don’t actually use them as methods outside of the class but simply as normal class properties. This is a neat thing that typescript does for us because we use the get and set keywords before we define the method. Read more on this in the link below.

On to Setters

So in this example, there’s really no need to have a setter because we don’t have a property that would be beneficial for our clients to have write access to. But for this case, lets go ahead and once again enable the ability to write to our savingsBalance property.

Keep in mind that setter methods can also take in other logic such as for the purposes for validating the inputs. Not always needed, but one more step to keep in mind for an added security measure.

Simple and easy, we create a set method that takes in a variable of the same type as the property that we are setting, and reset the property. Take a look.

We no longer get the read-only error, and We’re done here! (Just remember to remove the unnecessary setter method)

Signing Off

As we just saw, encapsulating the data held within the classes that we write should no longer be an option that’s ‘just there’; Encapsulation is a principle of Object Orient Programming and should be leveraged in every class you write from today until the day you retire as a developer. Encapsulation provides an important layer of protection over our priceless data and gives us that extra assurance to have a good nights sleep and not have to worry the fraudulent Banking Companies that Chuck unfortunately ran into.

Thank’s for reading, and please stay tuned for my next article discussing the next OOP principle on our list, Abstraction!

--

--

Raymond Johnson

Freelance software engineer with a passion for tech and progressing the knowledge of others, as well as myself with the things that will make us better devs.