Difference between type and interface?
In TypeScript, both 'type' aliases and 'interfaces' are powerful tools used for defining the shape of objects and other types. While they share significant similarities and can often be used interchangeably for object types, they have distinct characteristics and use cases that are important to understand.
Interface
An interface is a way to define contracts within your code and contracts with code outside of your project. They are primarily used to describe the shape of an object or to define the public contract for classes. Interfaces can declare properties and methods that an object must implement.
- Declaration Merging: Interfaces can be re-declared with the same name, and TypeScript will merge their definitions. This is useful for extending libraries or adding properties to existing interfaces.
- Implementation by Classes: Classes can implement interfaces using the
implementskeyword, ensuring they adhere to a specific structure. - Extensibility: Interfaces can extend other interfaces or type aliases using the
extendskeyword. - Primarily for Object Shapes: Best suited for defining the structure of objects.
Type Alias
A type alias creates a new name for a type. Type aliases are more versatile than interfaces because they can define aliases for any type, not just object shapes. This includes primitives, unions, tuples, intersections, and more complex type constructs.
- Versatility: Can alias any type, including primitives (e.g.,
string | number), union types (e.g.,string | number), tuple types (e.g.,[string, number]), and complex intersection types (e.g.,TypeA & TypeB). - No Declaration Merging: Type aliases cannot be merged. Re-declaring a type alias with the same name will result in a compilation error.
- Cannot be Implemented by Classes: Classes cannot directly implement type aliases in the same way they implement interfaces.
- Extensibility: Can extend/intersect with other types and interfaces using the
&operator (intersection types).
Key Differences Summarized
| Feature | Interface | Type Alias |
|---|---|---|
| Declaration Merging | Yes | No |
| Implementation by Classes | Yes (`implements`) | No (cannot directly implement) |
| Defining Primitive/Union/Tuple Types | No | Yes |
| Extensibility | Via `extends` (for interfaces/types) | Via `&` (intersection for any type) |
| Use Case | Primarily object shapes & class contracts | Aliases for any type, complex unions/intersections |
When to Use Which?
- Use
interfacewhen defining object shapes, especially if you expect future declaration merging (e.g., augmenting a third-party library's types) or if you are defining a contract that classes will implement. - Use
typewhen you need to alias a primitive, union, tuple, or a complex intersection type. It's also suitable when you need to define a type that is computed or derived from other types (e.g.,type MyType = A | B). - For object types, both can often be used interchangeably. However,
interfaceis generally preferred for its declaration merging capability and its conventional use for defining APIs and object contracts.