TypeScript-Handbook
TypeScript-Handbook copied to clipboard
don't recommend using interfaces over type aliases
The handbook recommends (in the Advanced Types section):
A second more important difference is that type aliases cannot be extended or implemented from (nor can they extend/implement other types). Because an ideal property of software is being open to extension, you should always use an interface over a type alias if possible.
I couldn't disagree with this more. There are many cases where an interface cannot be used for a type alias. You can only use an interface to type an object literal. If I am to follow this recommendation, then in a particular class file where I may have several type aliases, some will be type aliases and some will be interfaces. Someone stumbling upon this class will wonder what the heck is going on and if I am intending the interfaces to be implemented/extended somewhere, or to at least be expecting it to be a possibility.
It would be much cleaner in my opinion to use a type alias for a type alias and an interface for an interface, rather than substitute one for the other in some cases just because interfaces have some extra capability (that I don't need if all want is a type alias).
Why am I making such a big fuss of this? Well, is because tslint has taken this recommendation and made it into a recommended rule (interface-over-type-literal). Therefore this is imposed on anyone using tslint and trying to adhere to accepted best practices (as we are). I've written an issue against tslint as well but I think the docs should also be changed.
If there is agreement I'd be happy to submit a PR.
I don't think we're going to get anywhere by discussing stylistic preferences, so I need to be up-front and state that I don't think we're willing to change guidance at this point in time. Most of the decision is driven by semantics, not syntax. I'll explain why.
The only thing that isn't true anymore is that interfaces can extend and classes can now implement aliases of object types.
That said, there's a few things that are not great about type aliases:
- They're not guaranteed to have a nicely displayed representation.
- They can't be augmented/merged. (may be desirable)
- The compiler ends up doing more work comparing them, meaning compiler times take longer.
- The only way they can "extend" a type is through intersections, which provide no guarantees about property clashes.
Now while (1) and (3) are implementation details, it very much affects the lives of your consumers as well as your own codebase, so it really doesn't make sense for us to steer you towards this sort of pattern.
Why am I making such a big fuss of this? Well, is because tslint has taken this recommendation and made it into a recommended rule (interface-over-type-literal).
This is configurable - you are the Paula Abdul of your lint rule! Feel free to reconfigure it and standardize on one way within your organization or team. Consensus among your team is the most important thing.
I know that tslint is configurable, of course. We are trying to adhere to "community accepted best practices" with as few exceptions as possible and so far this is the only rule that really has me scratching my head. I'll get over it.
@DanielRosenwasser thanks for the explanation, very interesting 👍
- Is it by design? if so, would love to hear the motivation behind it
- How significant should it be? are there any benchmarks?
@DanielRosenwasser Could we hear about @GabiGrin 's questions and your opinion? Also, could I know when to use type aliases instead of interface?