Check out our Angular Book Series.

Create an Interface in TypeScript - - Part 7

I'm writing a series of articles about Typescript as extra material to support my upcoming Angular 4 book. This is the seventh part of that series. Check out part 1, part 2, Part 3, Part 4, Part 5. and Part 6.

This section will talk about interfaces. It is not about User interfaces, but rather object-oriented interfaces. An interface is a definition of properties and methods that must be supported by a class which implements this interface. You can think of an interface as the contract between a class instance and a method argument or variable. If they both match the interface they are interchangeable.

Create the Interface

For this sample, we're going to create a name interface. This interface will represent the name of a person and will contain a first name and last name. It will have an optional middle initial and also a method to retrieve the name. Here is the interface:


interface name {
firstName: string;
middleInitial? : string;
lastName: string;
getName() : string;
}

The interface is set up similar to a class or enum. It uses the keyword interface, and the name of the interface--in this case name. The firstName and lastName properties are as normal properties on an object. The middleInitial is an optional property, and that is distinguished by a question mark. Finally, a single method is defined by the interface, getName(). This will be used to return the name. The interface does not contain an implementation, just a definition of the method. That means different classes which extend the interface can have different implementations.

Rework the Echo Class

Let's rework the Echo class to use the interface instead of strings. First create the method stub with the instance variables:


class Echo {
static readonly messageIntro : string = "Hello"
subjectArray : name[];
private message : string;
}

The main change here is that the subject string was replaced with a subjectArray of name types. The constructor:


constructor(subjects : name[]){
this.subjectArray = subjects;
}

The constructor now accepts an array of name instead of a single string. The createMessage() function now loops over the array:


createMessage():void{
this.message = '';
for (let person of this.subjectArray){
this.message += Echo.messageIntro + " " + person.getName() + "<br/>";
}
}

Inside the loop, the interface's getName() function is used to add an element to the output. Finally, the echo() function:


echo():string{
return this.message;
}

The echo function has not changed, it just returns the object instance variable, message.

Implement the Interface with a Class

I'm going to create two classes which implement our name interface contract. One will be for a Person and another for a Pet. First, the Person class:


class Person implements name {
firstName: string;
middleInitial : string;
lastName: string;
getName(): string {
return this.firstName + ' ' + this.middleInitial + ' ' + this.lastName;
}
}

The class is defined with the class keyword followed by the name of the class. Then comes the implements keyword followed by the name of the interface. If you wanted you could list multiple interfaces here.

The firstName, middleInitial, and lastName are created properties on the object, not much different than how they were with the interface definition. The getName() method includes a definition. It concatenates the firstName, middleInitial, And lastName, returning a single string. Now, let's create another class that implements name. This one is called Pet:


class Pet implements name {
firstName: string;
lastName: string;
type : string;
getName(): string {
return this.firstName + ' ' + this.lastName + ", " + this.type;
}
}

This includes the firstName and lastName defined as variables on the class object. A new property is named type, this will represent the type of pet we have. A class can implement properties or methods not included in an interface. The middleInitial is left out, which is okay because that is marked as an optional property in the interface--and my pets don't have middle initials. The getName() method puts together the firstName and lastName, but appends the type to the end.

Create a name Array

We have an interface and two classes that extend it. Let's put all together. Start by creating a names array:


let nameArray : name[] = [];

Now create a new Person instance. This one represents me:


let jeffryInstance : Person = new Person();
jeffryInstance.firstName = "Jeffry";
jeffryInstance.middleInitial = "A";
jeffryInstance.lastName = "Houser";
nameArray.push(jeffryInstance);

The new jeffryInstance of the Person class is added to the nameArray.

Create two pets:


let hercInstance : Pet = new Pet();
hercInstance.firstName = "Hercules";
hercInstance.lastName = "Houser";
hercInstance.type = "Dog";
nameArray.push(hercInstance);

let zeusInstance : Pet = new Pet();
zeusInstance.firstName = "Isadora";
zeusInstance.lastName = "Houser";
zeusInstance.type = "Dragon";
nameArray.push(zeusInstance);

One is for my pet dog, Hercules, and the other is for my pet dragon, Isadora. Both are added to the same nameArray value without issue even though they have different types. The implementation of the interfaces tells the compiler that the nameArray can accept both Pet and Person instances.

Now, create an instance of the Echo class:


let echoInstance : Echo = new Echo(nameArray);

Create the message:


echoInstance.createMessage();

And output the message:


document.body.innerHTML = echoInstance.echo();

Recompile the app and load it in a browser:

It works as expected.

I have one more entry into this introduction to TypeScript series. It will tell you how to create Modules from your class and interface files.

Keep up to date by reading DotComIt's Monthly Technical Newsletter

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.