TypeScript Tip of the Week — Using Classes & Interfaces
By: Sam Redmond
Tags: JavaScript, Programming Tips, Learn To Code, Programming, Typescript

Hey guys, sorry I haven’t posted in a while I have been EXTRA busy the last few months! I am excited to be back with another TypeScript Tip. This week I want to talk about classes and interfaces. If you’re unfamiliar with interfaces they create a sort of structure for what an object or class is supposed to look like. They enforce that structure so that you will get an error if your class does not properly implement it.

When an interface enforces what an object structure is supposed to look like it also creates a contract with your code and outside code. To further explain this point, let’s have a look at an example.

// person-library.ts export interface IPerson {

firstName: string;

lastName: string;

age: number;

} export class Person implements IPerson {

firstName: string;

lastName: string;

age: number; constructor(data: IPerson) {

this.firstName = data.firstName;

this.lastName = data.lastName;

this.age = data.age;

} // Class Functions }

If you’re wondering why the interface is named IPerson instead of just Person , the I is usually used for interfaces as a general convention, but can also be used for interfaces that are implemented.

In this example, the Person class is implementing the IPerson interface. This means that the Person class must have all the properties of IPerson . Let’s assume that this is part of a person library that someone else is using. I mentioned that this can be used in external code to create a contract between the interface in the library and the external code.

// someone other code import { IPerson, Person } from 'person-library'; interface IEmployee extends IPerson {

jobTitle: string;

salary: number;

} class Employee extends Person implements IEmployee {

firstName: string;

lastName: string;

age: number;

jobTitle: string;

salary: number constructor(data: IEmployee) {

super(data); this.jobTitle = data.jobTitle;

this.salary = data.salary;

} // Class Functions

} const me = new Employee({firstName: 'Sam', lastName: 'Redmond', age: 100, jobTitle: 'Software Engineer', salary: 1000000});

This is a simple example showing exactly how the IPerson interface can be extended with additional properties. This pattern provides a general structure and allows for code reusability. I mentioned that interfaces create contracts in your code. This means that when we use an interface from some external code it is guaranteed that it will have certain properties. You can use that guarantee to assume that certain properties will exist.

Let’s break down this code a little bit. When we extend the IEmployee interface with the IPerson interface we don’t have to define the properties in IPerson . This is a useful feature of TypeScript so that you can declare interface properties once and then extend them later. We can do the same thing with the Employee class. When we extend a class we also have to use the super function in order to pass in the required information into the constructor of the extended class.

You will notice that we are passing in an IEmployee into the super function, but it should take an IPerson . Since IEmployee extends IPerson it must have all the properties of IPerson and can be used in its place in this case. This is an excellent example of creating contracts in your code using interfaces. Since all of the properties for IPerson have been initialized by our use of the super function we only need to initialize the properties unique to IEmployee .

Following this pattern gives you the ability to easily re-use chunks of code. This keeps your code neat and succinct which will help you maintain it in the long run. I hope you enjoyed this TypeScript tip. Since the holidays are over I should be able to continue posting regularly. I will be posting a new TypeScript tip every Wednesday evening.

Thanks for reading!