DEV Community

Linas Spukas
Linas Spukas

Posted on

 

TypeScript: Interfaces

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:

// 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:

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:

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:

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.

Top comments (0)

11 Tips That Make You a Better Typescript Programmer

1 Think in {Set}

Type is an everyday concept to programmers, but it’s surprisingly difficult to define it succinctly. I find it helpful to use Set as a conceptual model instead.

#2 Understand declared type and narrowed type

One extremely powerful typescript feature is automatic type narrowing based on control flow. This means a variable has two types associated with it at any specific point of code location: a declaration type and a narrowed type.

#3 Use discriminated union instead of optional fields

...

Read the whole post now!