In a discussion on language design on the Typescript discord about types vs interfaces, I tried to give a historical perspective to the complaints that interfaces seem designed for OO but have weird extra features.
A | B | C every time. Over time this expanded to intersections and mapped types.
The bottom line is that typescript has two nearly identical features for historical reasons, and there’s not a principled way to separate them or provide clear usage guidelines.
As @Retsam19 said, if we started over today, we’d probably only have type, although it would maybe have some way to include extends and merging. We’d likely have first-class
extends in the type system as an operator like intersection or spread (Typescript almost had first-class
spread in the type system.)
Specific complaints from @micuseym:
if all of this is intended, what are the benefits of this design? How do they outweigh the drawbacks?
Answer: it wasn’t intended; the benefits are: backward compatibility.
Interfaces seem like a feature designed specifically for OOP.
It’s more accurate to say that they were designed in a C#-like environment, where classes and namespaces were the way of structuring your program, not modules and closures (or something else).