"Import the type, not the value. The compiler can erase what you don't actually use at runtime."
What import type does
import type { User } from './types' imports only the type. At compile time, TypeScript records the dependency. At emit time, the import is removed entirely — no runtime cost, no bundler cost, no risk of accidentally including a heavy module just because you needed its type.
You'd use this when:
- The thing you're importing is only used as a type annotation (function parameters, return types, generics).
- The source module has side effects you don't want triggered (e.g., a module that registers globals on import).
- You're trying to break a circular dependency where one direction is type-only.
Inline type imports
Since TypeScript 4.5, you can mix value and type imports in one statement: import { Foo, type Bar } from './mod'. The type prefix marks individual items as type-only. The rest are value imports. This is convenient when a single module exports both runtime values and types you need.
verbatimModuleSyntax (tsconfig)
The verbatimModuleSyntax compiler option (TypeScript 5.0+) makes the import/export emission predictable: only import type and export type get erased; everything else stays. This avoids surprises where TypeScript's older 'isolated modules' heuristic erased imports it thought were unused. Modern projects should enable it.
import type whenever the import is type-only. The emitted JavaScript stays leaner, tree-shaking gets cleaner, and circular dependencies become easier to manage.