import type імпортує лише тип - такий імпорт гарантовано зникає з JavaScript після компіляції.
import type { User } from './models.js';
import { fetchUser, type Role } from './api.js'; // змішаний: fetchUser - значення, Role - тип
export type { User };
Навіщо, якщо TypeScript і так прибирає невикористані в коді імпорти типів:
1. Інструменти, що працюють з одним файлом. Babel, esbuild, SWC, стирання типів у Node.js перетворюють кожен файл окремо, не знаючи, що в іншому файлі User - це інтерфейс, а не клас. Для рядка import { User } from './models.js' вони не можуть вирішити, чи лишати імпорт. import type знімає неоднозначність.
2. Помилки виконання. Якщо імпорт типу лишився в JavaScript, а модуль нічого з такою назвою не експортує (інтерфейси під час виконання не існують), ES-модуль впаде: «The requested module does not provide an export named 'User'».
3. Побічні ефекти й цикли. Звичайний імпорт завантажує модуль і виконує його код. import type - ні. Це розриває циклічні залежності, що існують лише на рівні типів, і не тягне важкі модулі заради одного типу.
4. Читабельність - видно, що з модуля потрібні лише типи.
Прапорець verbatimModuleSyntax робить це обов'язковим: імпорт без type, у якому лише типи, - помилка компіляції. Рекомендований для нових проєктів.
Пастки:
import type { Foo }не можна використати як значення -new Foo()чиFoo.staticMethod()дадуть помилку. Для класу, який використовується і як тип, і як значення, - звичайний імпорт;import type X from(за замовчуванням) іimport type * as ns fromтеж працюють;- різниця
import type { A }іimport { type A }: зverbatimModuleSyntaxперший зникає повністю, а другий лишаєimport {} from './mod.js'- модуль усе одно завантажиться заради побічних ефектів.
Лінтер (@typescript-eslint/consistent-type-imports) автоматично виправляє імпорти на import type.