I see a lot of TypeScript developers overuse interface. In fact they use it for almost everything even if their code is more functional than object oriented. Personally I prefer type which is more flexible and doesn't confuse if the interface is implemented by any class or it's used just to define object type.
Are there any advantage to use interface over type or is it some kind of legacy thing that developers get used to do?
The intended use for type is for aliasing of types, especially intersection/union types.
They should not be used like an interface, as the documentation states:
As we mentioned, type aliases can act sort of like interfaces; however, there are some subtle differences.
One difference is that interfaces create a new name that is used everywhere. Type aliases don’t create a new name — for instance, error messages won’t use the alias name. In the code below, hovering over
interfacedin an editor will show that it returns anInterface, but will show thataliasedreturns object literal type.type Alias = { num: number } interface Interface { num: number; } declare function aliased(arg: Alias): Alias; declare function interfaced(arg: Interface): Interface;
The TS handbook clearly states that it is a matter of preference. There is no philosophical reason, no intent, no "should" or "shouldn't".
Type aliases and interfaces are very similar, and in many cases you can choose between them freely.
For the most part, you can choose based on personal preference, and TypeScript will tell you if it needs something to be the other kind of declaration.
Programmers who choose interfaces over type aliases do it out of habit, personal preference, or because they read the handbook and saw that last line just bellow:
If you would like a heuristic, use interface until you need to use features from type.
The reason why historically people had an objectively good reason to prefer interfaces by default was because classes could not implement a type alias and interfaces could not extend a type alias. This limitation was lifted with this PR.
You can see advice like in this article (paywall) all over the Internet, but as explained above, today they make no sense:
Interfaces can be implemented, extended, and merged, so they’re preferred to type literals.
1- Being able to do declaration merging with interfaces is not a reason to choose interfaces by default, but it has situational use cases, like supporting different versions of Javascript with d.ts files.
This is the case with RegExpMatchArray: depending on the lib you declare in tsconfig you will get one or both declarations, and they will be merged:
// from lib.es5.d.ts
interface RegExpMatchArray extends Array<string> {
/**
* The index of the search at which the result was found.
*/
index?: number;
/**
* A copy of the search string.
*/
input?: string;
/**
* The first match. This will always be present because `null` will be returned if there are no matches.
*/
0: string;
}
// from lib.es2018.regexp.d.ts
interface RegExpMatchArray {
groups?: {
[key: string]: string
}
}
Paired with module augmentation, interface merging is a great a way for users of a library to customize it.
A few caveats though:
2- Another technical reason to prefer an interface over an object type is that extending an interface is more efficient than intersecting 2 object literal types. If your objects are big, it can make a difference.
3- I am not convinced by the technical reason cited in Archimedes Trajano's answer: the example used in the supporting article would not even compile, which leads me to believe the author could not think of a single realistic scenario where this inlining would happen, but it is certainly something to consider when d.ts files get incomprehensibly large.
4- Finally, interfaces are great for type-level programming, but this is a completely different discussion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With