Specifically, the use of a type alias declaration effected a much larger
Yesterday I shrank a TypeScript declaration from 700KB to 7KB by changing one line of code 🔥
In the thread, Rob points out that the reason this happens is because type alias declarations can be inlined, whereas interfaces are always referenced by name.
Let’s have a look at some code that demonstrates this inlining behaviour.
Here’s a TypeScript playground snippet in which a type alias is used to declare the callback signature:
.d.ts output — which is shown in the playground’s right-hand-side panel — looks like this:
ReadCallback type alias is included in the
.d.ts output and the
read function’s signature refers to it by name.
The scoped type alias declaration won’t be included in the output and callback’s signature will be inlined:
IIFEs aren’t the only scenario in which inlining can occur. They’re used here so that inlining can be demonstrated in the TypeScript playground.
Inlining is something that won’t happen with interfaces, as interfaces are always referred to by name. If an interface is scoped in a similar manner, like this:
compilation will fail with an error:
Interfaces aren’t inlined. They are referred to by name and if the name is private, compilation will fail.
In early versions of TypeScript, the behavioural differences between type aliases and interfaces were significant. However, in recent versions there is less of a distinction and that has led to some developers preferring type aliases over interfaces.
The performance problems mentioned in Rob’s thread suggest that perhaps interfaces should be preferred. And Daniel Rosenwasser’s endorsement of interfaces is emphatic:
Honestly, my take is that it should really just be interfaces for anything that they can model. There is no benefit to type aliases when there are so many issues around display/perf.
We tried for a long time to paper over the distinction because of people’s personal choices, but ultimately unless we actually simplify the types internally (could happen) they’re not really the same, and interfaces behave better.
For developers interested in ensuring that interfaces are used wherever possible, I’ve added a
prefer-interface ESLint rule to
eslint-plugin-etc. It will effect a lint failure whenever it finds a type alias declaration that could be declared as an interface. The rule has a fixer — and a suggestion — and can replace type alias declarations automatically.
This post was first published on my personal blog: ncjamieson.com.