100 days of TypeScript (Day 4)

Wow. Day 4 already and we have already covered a lot of material in our quest to go from zero to, well not something cliched, with TypeScript. In the last couple of posts, we delved into using classes in TypeScript so, in this post, I would like to take a bit of a diversion and introduce you to interfaces. Now, if you have come from a language such as C# or Java, you probably think that you won’t learn anything new about interfaces here but interfaces in TypeScript are really cool.

Interfaces as data

One of the things you probably noticed when we were looking at classes is that they can have behaviour. In other words, they aren’t just about data, they also give you the ability to add functionality to manipulate the data. That is incredibly useful but sometimes we want the ability to create something to represent just the data itself. We want to be able to create a type-safe representation of some useful piece of data. You have probably jumped ahead already and thought “I bet Pete’s going to say that interfaces can solve this for me”, and you would be right.

For this post, we are going to create something that represents an email message. We will be able to add recipients, a subject, and the message itself. I am going to start off by writing an interface to represent a single recipient. To create an interface, I change the class keyword for interface so my recipient will look just like this.

interface Recipient {
    email: string;

If I wanted to create an instance of a recipient, I could do something like this.

const recipient: Recipient = { email: 'peter@peter.com' };

Variable declarations

As a side note, you will have seen that I have been declaring variables using the const keyword but I have not actually explained where it comes from or what it means. When I started talking about TypeScript, I briefly covered that it was developed to compile to JavaScript. JavaScript has three ways of declaring variables, var, let and const. Originally, JavaScript only had one way, using var, but this was highly problematic. A little while back, let and const were introduced to be a better, less troublesome form of declaration.

Let’s take a look at why var is such an issue. The issue is down to something called block scope. Block scope refers to where a variable can be seen – it should only be visible in the block that it is being declared in so it would probably come as a surprise that the following bit of code lets me see data that it shouldn’t.

for (var i = 0; i < 10; i++) {
console.log(i); // Wait, why can I see i here?

What we are seeing in this code is var keyword not being covered by the block scope. This can lead to unfortunate side effects in more complicated code because the value becomes unpredictable.

Enter our heroes, let and const.

These were introduced to help us declare variables that respect block scope. We have two keywords because let allows us to declare a variable and then change the value later on, whereas const allows us to declare the variable but it cannot be changed.

Back to our interface

I have created a simple recipient interface and now I am ready to add one that covers the email itself. The email interface will consist of To, CC and BCC recipients lists, as well as the Subject and Message. If we think about things before we start writing code, we make our lives a lot easier so I am going to ensure that the person using the email interface can choose which of the recipients they want to add. As we have a strong type for our recipient, I am going to use a little TypeScript trick and say that the recipients can receive an array of recipients or the recipient can be null using | null.

interface Email {
    To: Recipient[] | null;
    CC: Recipient[] | null;
    BCC: Recipient[] | null;
    Subject: string;
    Message: string;

The syntax of Recipient[] | null reads that I want an array of Recipient items OR I want it to be null.

Now that I have my interface, I am going to create a simple function that accepts an Email and write it to the console.

function sendMessage(message: Email) {

With all the bits and pieces discussed above, you will probably guess that the interface is going to be populated using the const keyword, just like this (this has to go before the sendMessage(email); line).

const email: Email = {
    To: [{
        email: 'bob@bob.com'
    CC: [{
        email: 'terry@terry.com'
    }, {
        email: 'chris@chris.com'
    BCC: null,
    Subject: 'This is my email',
    Message: 'This is the message inside my email'

Notice that I still had to add the BCC. Without this part, the “shape” of the object would not match the interface and TypeScript is really good at catching things like that.

A quick note about adding individual items to an array. In the recipient entries, each recipient was surrounded by { }. This is how we add an individual entry into the array, so adding multiple ones is simply a matter of separating these { } pairs with a comma.

We have reached the end of our introduction to interfaces. They can do so much more so, in the next post, I am going to show how classes and interfaces work together.

The code for this post can be found on github.


6 thoughts on “100 days of TypeScript (Day 4)

  1. Pingback: Dew Drop – November 1, 2021 (#3549) – Morning Dew by Alvin Ashcraft

  2. Pingback: Dew Drop – November 1, 2021 (#3549) - Online Code Generator

  3. Pingback: ➧Dew Drop – November 1, 2021 (#3549) • Softbranchdevelopers

  4. Pingback: 100 days of TypeScript (Day 5) – Confessions of a coder

  5. Pingback: 100 days of TypeScript (Day 5) | Tech Programing

  6. Pingback: The Morning Brew - Chris Alcock » The Morning Brew #3344

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s