C.W.K.
Stream
Lesson 02 of 05 · published

`import type` and Verbatim Module Syntax

~8 min · modules, import-type, type-only

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"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.

Use import type whenever the import is type-only. The emitted JavaScript stays leaner, tree-shaking gets cleaner, and circular dependencies become easier to manage.

Code

import type — separate and inline forms·typescript
// types.ts — exports both a value and a type.
export function createUser(name: string): User { /* ... */ return {} as User }
export interface User { name: string; email: string }

// consumer.ts — type-only import.
import type { User } from './types';
import { createUser } from './types';   // value import — separate

function welcome(u: User): string {     // type-only use
  return `Welcome, ${u.name}`;
}

const u = createUser('Pippa');           // value use
console.log(welcome(u));

// Inline mix.
import { createUser, type User } from './types';   // same thing in one line

// What the .js output looks like:
// import { createUser } from './types';
// function welcome(u) { return `Welcome, ${u.name}` }
// const u = createUser('Pippa');
// console.log(welcome(u));
// — the `type` import is erased.

External links

Exercise

Take a file that imports both a function and a type from the same module. Convert the type import to import type (or inline type marker). Look at the compiled JavaScript output — confirm only the function import remains.
Hint
Before: one import line covers both. After: either two lines (one regular, one import type) or one line with the inline type marker. The emitted JS has only the value import.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.