Skip to main content

TypeScript: Interfaces

Interfaces

We briefly touched on interfaces in the types post:

TypeScript: Types

But let's dive a little deeper into what interfaces are and how they can be used.

Type Aliases vs Interfaces

While both aliases and interfaces can be used to describe the shape of an object, there are some differences and specific use cases for each.

  • Interfaces: Can be extended or implemented, making them more flexible for defining object shapes and contracts.
  • Type Aliases: Are more suitable for defining complex types, such as unions or intersections, and for creating descriptive names for types.

A key thing to note is that aliases cannot be modified or extended after they are defined, whereas interfaces can be extended to add new properties or methods.

Example: Type Alias

type Point = {
x: number;
y: number;
};

type ID = string | number;

Example: Interface

interface Point {
x: number;
y: number;
}

interface ID {
id: string | number;
}

Extending Interfaces

Interfaces can be extended, allowing you to build complex types based on existing ones. This is useful for creating hierarchies or adding properties to existing interfaces.

interface Person {
name: string;
age: number;
}

interface Employee extends Person {
employeeId: number;
position: string;
}

let employee: Employee = {
name: "John Doe",
age: 30,
employeeId: 1234,
position: "Developer",
};

Interface Declaration

Interfaces can be declared to define the structure of objects, ensuring they have specific properties with specific types.

interface User {
id: number;
name: string;
email: string;
}

let user: User = {
id: 1,
name: "Alice",
email: "alice@example.com",
};

Hybrid Interface Types

In TypeScript, a hybrid type is a type that combines multiple types into a single type. The resulting type is considered a union of those types. This allows you to specify that a value can have multiple types, rather than just one.

For example, if we create a simple union type that can accept either a string or a number:

type StringOrNumber = string | number;

we could then roll that hybrid alias type up into a hybrid interface:

type StringOrNumber = string | number;

interface User = {
id: StringOrNumber;
name: string;
age: number;
email: string;
};

or you can roll an interface into a hybrid interface type as it's own type

interface Education = {
degree: string;
school: string;
year: number;
};

interface User = {
name: string;
age: number;
email: string;
education: Education;
};
tip

This also works for alias types

type Education = {
degree: string;
school: string;
year: number;
};

type User = {
name: string;
age: number;
email: string;
education: Education;
};

Here is a more advanced hybrid interface example uses a callable signature, a method and a simple property.

📘 typescriptlang.org > #call-signatures

In this example we create an interface Counter that acts as a function and an object with properties.

interface Counter {
(start: number): string; // callable signature, takes number, returns string
interval: number;
reset(): void;
}

function createCounter(): Counter {
// Create a function that matches the callable signature
let counter = <Counter>function (start: number) {
console.log(`Counter started at ${start}`);
return `Counter started at ${start}`;
};
counter.interval = 1000;
counter.reset = function () {
console.log("Counter reset");
};
return counter; // returned object matches the Counter interface
}

let myCounter = createCounter();
myCounter(10); // Outputs: Counter started at 10
myCounter.reset(); // Outputs: Counter reset
console.log(myCounter.interval); // Outputs: 1000

Clarifications

  • Hybrid Types: Hybrid types in TypeScript often refer to types that combine object properties and callable signatures, as shown in the Counter example. They are not the same as union types, which allow a variable to hold values of different types.
  • Interfaces and Type Aliases: Both interfaces and type aliases can define the structure of an object, but interfaces are generally more flexible for extending and merging, while type aliases are more versatile for defining complex types like unions and intersections.
  • Callable Signature: The line (start: number): string; in the Counter interface specifies that the object can be called as a function that takes a number and returns a string.

Automated Amazon Reports

Automatically download Amazon Seller and Advertising reports to a private database. View beautiful, on demand, exportable performance reports.

bidbear.io