Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Typescript

100 Days of TypeScript (Day 4)

3.67/5 (2 votes)
30 Oct 2021CPOL4 min read 5K  
An introduction to interface in TypeScript
This is Part 4 of a 100 part series introducing you to TypeScript if you’ve not used it before; which will give you a brush up on things you already know if you’ve used it, and maybe introduce you to some new things that you might not have come across before. In this part, you will learn a little about interfaces in TypeScript.

Wow. Day 4 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.

JavaScript
interface Recipient {
    email: string;
}

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

JavaScript
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.

JavaScript
for (var i = 0; i < 10; i++) {
  console.log(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.

JavaScript
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.

JavaScript
function sendMessage(message: Email) {
    console.log(message);
}
sendMessage(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).

JavaScript
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)