TypeScript: Interfaces
Tags: typescript
Published: 2020-05-31 09:33:33

TypeScript has a feature, an Interface, that let you create custom data types, very similar to already existing types, like strings, numbers or booleans. Interfaces contain properties, such as named types and methods, and shape, that objects or classes have to implement.

## What problem does it solve?

By writing Interfaces we tackle couple main obstacles. First one is readability. With interface the code becomes more readable by replacing long annotations with an Interface, like in the following example:

```ts
// with object literal annotation
const person: { name: string; age: number; isFriend: boolean } = {
	name: "John",
	age: 30,
	isFriend: true,
};

// with Interface
interface Person {
    name: string;
    age: number;
    isFriend: boolean;
}

const person: Person = {
	name: "John",
	age: 30,
	isFriend: true,
};
```

Second, it solves the repeatability problem. If you have several places with the same value types, it is easy to reuse the defined Interface. In the next example we will reuse Person interface to annotate array and a function argument:

```ts
interface Person {
	name: string;
	age: number;
	isFriend: boolean;
}

const friendsList: Person[] = [];

function addToFriendsList(person: Person): void {
	friendsList.push(person);
}

addToFriendsList({
	name: "John",
	age: 30,
	isFriend: true,
});
```

## Syntax

Interfaces has no restrictions what comes to data types. You can define strings, numbers, booleans, complex objects, arrays, tuples or functions:

```ts
interface Person {
    name: string;
    age: 30;
    isFriend: true,
    friendsWith: string[]; // array of strings
    getName() : string; // a function that returns a string
    createdAt: Date; // an instance of a Date object
}
```

Interface makes sure, that data meet defined criteria and not the other way around. In other words, objects or classes must have at least the same properties as defined in an Interface. The Interface does not care if the data will have more fields, it makes sure, that it has at least those types that are defined. Take the following example, where the object literal can be applicable to both Interfaces, even though they consist of a different structure:

```ts
interface Person {
    name: string;
    getName() : string;
}

interface Summary {
    getName(): string;
}

function printName(person: Person): void {
    console.log(person.getName());
}

function printName(person: Summary): void {
    console.log(person.getName())
}

const friend = {
    name: "John",
    age: 30,
    getName() {
        return this.name;
    }
};

printName(friend)
```

Function `printName` in one case receives `Person` and in another `Summary` Interfaces. Both cases will be validated correctly because the `friend` object has met their requirements; has `getName()` and `name` properties. Interfaces do not care about other fields, such as `age`.

## Summary

The main purpose of Interfaces is to add a protection layer for data to meet the requirements. In other words, objects and classes must implement the defined Interface structure to be usable. Additionally, Interfaces make the code more readable and less repeatable.