27.5. Classes and Interfaces in TypeScript

27.5.1. Classes

Classes in TypeScript look something like this:

 1class Astronaut {
 2   name: string;
 3   constructor(firstName: string, lastName: string) {
 4      this.name = firstName + " " + lastName;
 5   }
 6   greet() {
 7      return "Hello, " + this.name;
 8   }
 9}
10
11let Bob = new Astronaut("Bob","Smith");

You may remember the this and new keywords from working with classes in JavaScript. Earlier in the chapter, we also noted that when declaring variables in TypeScript, we have to specify the type of value. The same applies to function parameters, as you can see in the constructor.

When using inheritance, classes in TypeScript can also use the extends keyword to denote child and parent classes, as shown here:

 1class Panthera {
 2   roar: string;
 3   constructor(currentRoar: string) {
 4      this.roar = currentRoar;
 5   }
 6}
 7
 8class Tiger extends Panthera {
 9   stripes: boolean = true;
10
11}
12
13let tigger = new Tiger("loud");
14console.log(tigger.roar);
15console.log(tigger.stripes);

27.5.2. Interfaces

Interfaces are not used in JavaScript, but are important in TypeScript. Like classes, interfaces define properties and methods that a type will have. The difference is that interfaces do NOT include initialization of properties or implementations of methods.

Note

Though the use of interfaces in Angular is not within the scope of this book, interfaces are used rather frequently in Angular code and are important in object-oriented programming languages, such as Java.

We may create an interface for a data type that contains all of the information we need about an astronaut and then use that information in a function.

 1interface Astronaut {
 2   name: string;
 3}
 4
 5function astronautName (astronaut: Astronaut): string {
 6   return astronaut.name;
 7}
 8
 9let bob = {name: "Bob"};
10console.log(astronautName(bob));

Interfaces define the contract that other classes or objects must comply with if implementing that interface. Multiple classes can implement one interface, and that flexibility allows different classes to share one type. This can be helpful when a function parameter needs to make use of certain behaviors.

1interface interfaceName {
2   someProperty: number;
3}
4
5class className implements interfaceName {
6   constructor(x: number) {
7      this.someProperty = x;
8   }
9}

Example

 1interface Panthera {
 2   roar: string;
 3}
 4
 5class Tiger implements Panthera {
 6   roar: string;
 7
 8   constructor() {
 9      this.roar = 'rooooaaaarrrr';
10   }
11}
12
13class Lion implements Panthera {
14   roar: string;
15
16   constructor() {
17      this.roar = 'ROOOOAAAAARRRRRR';
18   }
19}
20
21function pantheraSounds(panthera: Panthera): void {
22   console.log(`Panthera says ${panthera.roar}`);
23}
24
25let tiger = new Tiger();
26let lion = new Lion();
27
28pantheraSounds(tiger);
29pantheraSounds(lion);

In this example, the Panthera interface defines the roar property. Tiger and Lion implement the Panthera interface, which means Tiger and Lion must have a roar property.

The function pantheraSounds has one parameter of type Panthera. The variables tiger and lion can be passed into pantheraSounds because they are instances of classes that implement the Panthera interface.

27.5.2.1. Optional Parameters

null and undefined are primitive data types in TypeScript, however, they are treated differently by TypeScript. If you are planning on using null to define a property of an interface that is not known yet, use the TypeScript optional parameter, ?.

Let's take a look at how that would look in TypeScript.

In JavaScript, we might have an object that looks like so:

1let giraffeTwo = {
2     species: "Reticulated Giraffe",
3     name: "Alicia",
4     weight: null,
5     age: 10,
6     diet: "leaves"
7};

If we wanted to declare the same object as an interface in TypeScript, we would have to use the optional parameter for the weight property.

1interface giraffeTwo = {
2     species: string;
3     name: string;
4     weight?: number;
5     age: number;
6     diet: string;
7};

27.5.3. export

In TypeScript, you can use the export keyword to make classes and interfaces available for import in other files. This will look familiar to you as you saw something similar with modules.

Using the export keyword looks something like this:

1export class className {
2   // properties and methods
3}

27.5.4. import

In TypeScript, you can use the import keyword to use classes and interfaces declared in other files available for use in the file you are working on. This is a similar idea to importing modules, however, the syntax is different in TypeScript:

1import { className } from 'relativefilepath';
2
3let newClass = new className;

27.5.5. Check Your Understanding

Question

What is the difference between a class and an interface?