Should I use “import type” in TypeScript? Stop Guessing What Your Compiler is doing.
How TypeScript 5.0’s compiler option makes your code more predictable, bundler-friendly, and noticeably cleaner.
Should I use “import type” in TypeScript? Stop Guessing What Your Compiler is doing.

How TypeScript 5.0’s compiler option makes your code more predictable, bundler-friendly, and noticeably cleaner.
If, like me, you have spent some time in the TypeScript ecosystem, you might have noticed that some projects, or some developers, choose to add a type keyword before type imports.
At first, I was super confused; on the face of it there appears to be no difference. (Un)fortunately the devil’s in the details with all things programming. In this case we need to look at something called “Type Elision”
Type E-what?
Historically, TypeScript has tried to be exceptionally smart about your imports. If you import something from another file but only use it as a type annotation, TypeScript will silently remove (or “elide”) that import from the final emitted JavaScript.
Why? Because JavaScript doesn’t have types. If the import stayed, the browser or Node.js environment might try to load a module that doesn’t actually exist at runtime, causing a crash.
Bu-buh, it works on my machine
Honestly, good for you. But for us toolchain-challenged mortals we might run into some problems.
In the good-old-days of TypeScript things were a bit more simple. Whenever we want to run some code we would use tsc, the formal way to crunch some .ts files and spit out nice executable .js files.
But things move fast in web development. Since then, maintainers of JS bundlers realised that they could write their own plugins to strip out TypeScript syntax.
This is the absolute fastest way to compile TypeScript. No type-checking. No context building. No knowledge of the type system. Just turn my file into JavaScript already.
This is great when you want to move quickly, like when you don’t care about type safety and just want instant feedback. To be honest, in my day-to-day life this is what I want most of the time. I need to switch things up and get instant feedback either from a script or from the browser. I only batten down the hatches at the end with maximal type safety when I am ready to ship.
But with speed comes a tradeoff: if these bundlers are so much faster, why is tsc so much slower?
As mentioned, tsc needs to ensure the correctness of your program by passing it through its type checker. To do this it needs to fully map your type system and understand it. Every import must be followed and understood. This means a laborious file-by-file workflow which is great for checking correctness, but not so great for prototyping or instant feedback.
So what’s this really about?
The magic of type elision only holds up when your compiler is combing through your project and understanding the value on the other end of an import. If you import a runtime value and a transient type in the same file, tsc is smart enough to erase the latter in your output file.
However if you use one of these faster options (which I recommend you do), then you run the risk of losing some of your gained performance. Or in an absolute worst-case scenario, seeing a crash at runtime.
How It Works in Practice
If you import something without the type keyword, tsc, our teacher’s pet will go and thoroughly check if your value needs to be present in the output file:
// app.ts
import { User } from "./models"
import { Button } from "./components"
// models.ts
export interface User {
email: string
name: string
}
// uh-oh, I hope I can avoid running this code if I don't need to...
export const AScarilyHugeValue = "..."
In this case, we checked models.ts and found that User does not need to exist at runtime. Let’s omit it from the output file!
// app.js (compiled by tsc)
import { Button } from "./components"
Great! Now we do not have to worry any side-effects in the models file, especially not loading in that huge value!
If you instead rely on a lightspeed single-file compiler, perhaps even compiling many files in parallel, you might not get the same result:
// app.js (compiled by a speedy web compiler)
import { User } from "./models" // <- still included
import { Button } from "./components"
So why is this a problem again? For a start you could end up importing unnecessary side effects into your file. Side effects that make app.js depend on models.js mean that any change in models will invalidate the cached build of app.js! Not good.
In a worst case scenario your compiler has no fallback for the ghost import and you will see a runtime crash!
// models.js
export {} // <- erased by compilers
Enter verbatimModuleSyntax
Introduced in TypeScript 5.0, verbatimModuleSyntax is designed to replace older, more confusing flags like importsNotUsedAsValues and preserveValueImports.
Its philosophy is incredibly straightforward: What you write is what you get.
If you write an import, TypeScript will leave it alone. If you want TypeScript to remove the import in the compiled JavaScript, you have to explicitly tell it to do so using the type modifier. No more guessing. No more compiler magic.
How to Enable It
Simply drop this into your tsconfig.json:
JSON
{
"compilerOptions": {
"verbatimModuleSyntax": true
}
}
So should you use it?
Unless you’re doing a quick and dirty piece of work, I highly recommend incorporating this flag into your preferred build ruleset.
- It plays perfectly with Vite, esbuild, Babel, and SWC by making every file safely transpilable in isolation.
- You never have to wonder if an import will survive compilation. If it lacks the
typekeyword, it stays. - It forces you and your team to be extremely intentional about distinguishing between types and runtime values.
- It replaces deprecated flags (
importsNotUsedAsValues, etc.), ensuring your config aligns with modern TypeScript standards.
The Takeaway
TypeScript is at its best when it provides guardrails, not when it acts as an invisible hand rearranging your code.
By enabling verbatimModuleSyntax, you are taking back control of your module structure. It might require you to be a bit more explicit with your type keywords, but the trade-off is a vastly more predictable, stable, and bundler-friendly codebase.
메타데이터
- post_id
- d108009884a2
- slug
- should-i-use-import-type-in-typescript-stop-guessing-what-your-compiler-is-doing-d108009884a2
- url
- https://medium.com/@ejaustinforbes/should-i-use-import-type-in-typescript-stop-guessing-what-your-compiler-is-doing-d108009884a2
- canonical_url
- https://medium.com/@ejaustinforbes/should-i-use-import-type-in-typescript-stop-guessing-what-your-compiler-is-doing-d108009884a2
- author_url
- https://medium.com/@ejaustinforbes
- status
- ok
- fetched_at
- 2026-07-11 09:44:05