TypeScript type only imports and exports

How to use Type-Only imports and exports with TypeScript

TypeScript logo, marking a guide to type-only imports and exports

A few months back, I started seeing strange warnings in Webpack about exports that could not be found.

I was puzzled. Obviously, there was something wrong, since the export was really there:

And I couldn’t notice what was wrong where I was using that type:

Can you spot the problem?

The root cause…

After digging for a little while without having a clue, I’ve stumbled on the following issue: https://github.com/webpack/webpack/issues/7378

I had a feeling it has something to do with TypeScript & transpilation, since I was importing/using a TypeScript type, but it wasn’t clear…

And then it clicked; Tobias Koppers immediately saw what I failed to understand. I was “ashamed” since I had just published a book about TypeScript :D

The thing is that once TypeScript code is transpiled, interfaces/types are gone. They don’t exist anymore; they don’t exist in the emitted files.

What I didn’t think much about before is that while the types are erased, the imports/exports aren’t necessarily. The reason is that there are ambiguities and that the compiler doesn’t always know for sure whether something that is exported is a type or a value.

In my particular case, what Webpack saw when it processed the resulting JavaScript code is that an import was there for something that didn’t exist.

Webpack was lenient, so it only emitted a warning, but the issue was indeed really there and I had no control over what TypeScript generated in that case.

TypeScript 3.8 to the rescue

I didn’t have much time to look further into the issue at that point, so I let it rest for a while (it wasn’t blocking), but later, once TypeScript 3.8 was released, I noticed something really interesting in the release notes: Type-Only Imports and Exports.

It directly reminded me of my import issue…

This new feature of TypeScript added the possibility to import an element only as a type, precisely for cases where a type is imported only to be used as a type and never as a value. And this was exactly what I needed; thanks to this I could finally tell the compiler precisely what I wanted to do.

To fix the problem, I simply had to replace this

import { MyCustomExpressRequest } from "../../../shared";

By the following:

import type { DidowiExpressRequest } from "../../../shared";

Wonderful!

But what does this change in practice?

Well, as the TS release notes explain, by importing an element using “import type”, it tells the compiler that the element is only imported to be used as a type annotation/declaration. Thanks to this, the compiler knows that it can erase the import in the emitted code.

With this single change done, Webpack was immediately happier: no more weird imports!

Note that you can also use export type to indicate that some export will only ever be used as a type annotation/declaration.

Finally, the behavior can be further configured through the importsNotUsedAsValues flag.

Conclusion

TypeScript Type-Only imports/exports are a useful addition to the language, allowing us to have more fine-grained control over what TypeScript does for us, hence allowing us to handle some annoying “edge cases” like this one.

A word of warning though: don’t go overboard with this ;-)

PS: If you want to learn tons of other cool things about TypeScript, Angular, React, Vue and other cool subjects, then don’t hesitate to grab a copy of my book and to subscribe to my newsletter!

That's it for today! ✨


Go Further

How to mock TypeScript method overloads with Jest
Learn how to mock TypeScript method overloads with Jest
How to implement input validation with NestJS
Learn how to validate incoming data with NestJS
Introduction to TypeScript
What is TypeScript? Let's find out!

Want to go deeper?

Knowii Community - Master Knowledge Management + AI | From €4.99/month
Join 400+ members mastering Knowledge Management AND AI. Community + Courses + Tools integrated. €500+ value in Knowledge Master tier.

About Sébastien

I'm Sébastien Dubois, and I'm on a mission to help knowledge workers escape information overload. After 20+ years in IT and seeing too many brilliant minds drowning in digital chaos, I've decided to help people build systems that actually work. Through the Knowii Community, my courses, products & services and my Website/Newsletter, I share practical and battle-tested systems.

I write about Knowledge Work, Personal Knowledge Management, Note-taking, Lifelong Learning, Personal Organization, Productivity, and more. I also craft lovely digital products and tools.

If you want to follow my work, then become a member and join our community.

Ready to get to the next level?

Want to level up as a developer?

Found this valuable? Share it with someone who needs it.

Join 6,000+ readers. Get practical systems for knowledge & AI. Free.

Subscribe ✨

Free: Knowledge System Checklist

A clear roadmap to building your own knowledge system. Subscribe and get it straight to your inbox.

6,000+ readers. No spam. Unsubscribe anytime.