The Differences Between Type and Interface in Typescript

The Differences Between Type and Interface in Typescript

Typescript is a superset of JavaScript that incorporates static typing, making detecting errors simpler and producing more maintainable code.

Types and interfaces in Typescript represent two distinct methods for defining the structure and shape of values or objects. They help ensure that variables, objects, arrays, parameters, and function return values match the structure and type set by the developer. This article emphasizes the distinctions between types and interfaces and their appropriate use cases.

Types

Types describe a value type such as string, boolean, number, etc. It enables you to explicitly specify the data type of variables, objects, function parameters, and function return values of functions, for example:

//types in variables
const age: number = 24;


//types in functions
function addNumbers(a: number, b: number): number {
  return a + b;
}

You can also use types to describe an object's structure or shape.

//type alias
type User = {
  id: string;
  firstName: string;
  lastName: string;
  isAdmin: boolean;
  age: number;
};

Interfaces

Interfaces allow you to specify the shape of an object by declaring the properties it should have, along with their types and optionally their accessibility modifiers.

The Differences

Below are some key differences between an interface and a type in typescript:

Types can be used to describe primitive types

One key distinction between interfaces and types is that only types can describe primitive types.

In the following code, the type declarations are suitable for describing the shape of data that isn't an object, but they are not valid for interface declarations.


// Types
// works fine with types
type Status = "pending" | "success" | "error";
type FamousQuotes = string[] | undefined;


 //Interface
 //Error! parsing error "{" expected
interface IStatus = "pending" | "success"

Interfaces for declaration merging

One advantage interface has over type is that you can always reopen them to add more properties. this is not possible when using type.

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

// Reopen the Person interface and add a new property
interface Person {
  gender: string;
}

const person: Person = {
  name: "John",
  age: 25,
  gender: "Male",
};

console.log(person.name); // Output: John
console.log(person.age); // Output: 25
console.log(person.gender); // Output: Male

When using type this would throw an error:

type Person = {
  name: string;
  age: number;
}

// Error: "Duplicate identifier 'Person'"
type Person = {
  gender: string;
}
// Error: Object literal may only specify known properties, and 'gender' does not exist in type 'Person'
const person: Person = {
  name: "John",
  age: 25,
  gender: "Male",
};

Interface extension and type union

When working with objects and classes, interfaces offer a more seamless experience, allowing you to extend other interfaces to inherit their properties and methods.

interface Animal {
  name: string;
  age: number;
  eat(): void;
}

interface Dog extends Animal {
  breed: string;
  bark(): void;
}

const myDog: Dog = {
  name: "Max",
  age: 3,
  breed: "Chihuahua",
  eat() {
    console.log("Eating...");
  },
  bark() {
    console.log("Woof!");
  },
};

console.log(myDog.name); // Output: Max
console.log(myDog.age); // Output: 3
myDog.eat(); // Output: Eating...
myDog.bark(); // Output: Woof!

However, we can perform something known as "intersection types" with types. Intersection types allow you to combine multiple types into a single type with all the properties and methods of each type. This is achieved by using the & symbol between the different types.

// type

type Animal = {
  name: string;
  age: number;
  eat(): void;
}

type Dog = Animal & {
  breed: string;
  bark(): void;
}

VS Code IntelliSense performs better with types.

When using types, you can hover over the type declaration, and IntelliSense in VS Code displays the internal properties of that type. However, interfaces only show the name of the declared interface. A related issue can be found on GitHub, as this is a significant factor for some people to prefer using types over interfaces.

Intellisense on VS Code when using interface:

Intellisense on VS Code when using type:

Comparison Table

The table below compares types and interfaces in TypeScript:

TypeInterface
Syntaxtype TypeName = ...interface InterfaceName { ... }
DeclarationCan be named or anonymousMust be named
MergingCan be extended using intersection (&)Can be extended using the extends keyword
ImplementationCannot be implemented directlyCan be implemented by classes and objects
ExtendableCannot extend or be extendedCan extend other interfaces
IntersectionCan be used in intersection typesCannot be used in intersection types
UnionCan be used in union typesCannot be used in union types
Declaration mergingCannot merge declarations of the same nameCan merge declarations of the same name
Discriminated unionCannot be used in discriminated unionsCan be used in discriminatory unions
Function-likeCan define callable and constructible typesCannot define callable or constructible types

Which should I use for a typescript project?

Often, as someone starting with TypeScript, you might ask yourself, "When should I use 'type' over 'interface' and vice versa?" The comparison above shows that both have different approaches to describing the shape of values and objects in your TypeScript project.

A short, opinionated answer is to use interfaces until you encounter areas where you need to explicitly use types, as interfaces represent how Javascript behaves in a real-world scenario. However, it boils down to a matter of personal preference. This Stackoverflow discussion also highlights different developers' choices and reasons for picking interfaces over types and vice versa.

Conclusion

In this article, we explored some of the differences between types and interfaces in typescript and the best occasions to use one over the other. Ultimately, the decision of whether to use type or interface in a TypeScript project depends on your personal preference and the specific needs of your project. Both have their own strengths and weaknesses, and it's up to you to weigh them and make an informed decision. It's also worth noting that as you gain more experience with TypeScript, your preferences, and needs may change, so don't be afraid to experiment and try different approaches.

Reference

I'd love to connect with you on Twitter | LinkedIn | GitHub

Thanks for reading; I hope you find this article helpful. Cheers

Did you find this article valuable?

Support Jamin's notes by becoming a sponsor. Any amount is appreciated!