Post Content

Interface vs Type – A Comprehensive Guide
If you’re new to Typescript, and have watched tutorials/read code blocks from the internet you have probably encountered both “types” and “interfaces”. While both serve similar purposes, they have distinct features and use cases. In this article i hope to help you understand when to use which one.
Similarities Between “interface” and “type”
Both “interface” and “type” can:
-
Describe object shapes Both can define the structure of an object, including its properties and their types.
-
Be extended or composed You can build upon existing “interface” or “type” definitions.
-
Work with classes Both can be implemented by classes to enforce type-checking.
-
Be used for type-checking Both are erased during compilation and exist only for compile-time type-checking.
Example: Equivalent Definitions
//Using type
type TPerson = {
id: number;
name: string;
};
//Using interface
interface IPerson {
id: number;
name: string;
}
const johnny_cash: IPerson = { id: 0, name: "Johhny" };
const sturgill_simpson: TPerson = { id: 0, name: "Stu" };
//Virtually the same f*cking thing
Side note, but I don’t like naming conventions for types or interfaces in which the first letter of the interface is “I”, I’m just writing it like that for visual purposes.
Differences Between “interface” and “type”
Feature | interface | type |
---|---|---|
Inheritance | ✅ Can be extended with “extends” | ✅ Can use intersection ”&“ |
Declaration Merging | ✅ Yes – multiple declarations merge | ❌ No – duplicate declarations error |
Union & Intersection Types | ❌ No | ✅ Yes |
Primitives, Tuples, Functions | ❌ No | ✅ Yes |
Mapped & Conditional Types | ❌ No | ✅ Yes |
Implements (Class) | ✅ Yes | ✅ Yes |
Complex Type Compositions | ❌ Limited | ✅ Preferred |
Performance limitations?
Runtime
At runtime, there’s no performance difference between “interface” and “type” because TypeScript types are erased during compilation.
Compile-Time
- interface: Faster to compile and more memory-efficient in large projects.
- type: More flexible but can lead to slightly slower compile times when heavily used with complex intersections/unions.
When to Choose One vs the Other
Scenario | Recommendation | Reason |
---|---|---|
Declaring object shapes or class contracts | interface | More readable, extendable, and optimized by the TypeScript compiler. |
Declaring union/intersection types | type | Interfaces can’t express unions or intersections. |
Working with primitives, tuples, functions | type | Only “type” supports non-object types. |
Need declaration merging | interface | Only “interface” supports merging. |
Complex type expressions | type | Easier composition with advanced types. |
Library/public API design | interface | Easier to extend without breaking changes. |
Extending Types vs Interfaces
// Using interface extension
interface A { x: number; }
interface B extends A { y: number; }
// Using type intersection
type A = { x: number };
type B = A & { y: number };
Union with Types Only
type Status = 'success' | 'error' | 'loading';
Function Types
type Log = (message: string) => void;
Rule of Thumb
Use interface for objects and class shapes when you expect extensions. Use type for composing multiple types, unions, or anything more complex than a straightforward object.
Sometimes interfaces with complex types inside of them will require you to use both:
type Status = 'success' | 'error';
interface Record {
id: string;
title: string;
status: Status;
}
Conclusion
This is one of the topics in which, by keep cooding you’ll figure out when to use which one.