ПрограммированиеFrontend разработчик / Fullstack разработчик

Как работает система модулей в TypeScript, и что отличает её от модулей JavaScript? В чем особенности деклараций типов и экспорта с TypeScript?

Проходите собеседования с ИИ помощником Hintsage

Ответ

TypeScript поддерживает обе основные системы модулей JavaScript — CommonJS и ES Modules, позволяя использовать ключевые слова import и export для организации кода. Отличие TypeScript — наличие деклараций типов, которые могут экспортироваться и импортироваться так же, как и значения.

Например, можно экспортировать интерфейс:

// types.ts export interface User { id: number; name: string; } // index.ts import { User } from './types'; const u: User = { id: 1, name: 'Alice' };

Также поддерживаются export type, export interface, import type, что позволяет импортировать только типы без подтягивания кода в финальный bundle, что оптимизирует сборку:

import type { User } from './types';

Важная особенность: в TypeScript можно экспортировать только типы, которые не попадут в итоговый JavaScript.

Вопрос с подвохом

Какая разница между import { SomeType } from './file' и import type { SomeType } from './file'?

Неверный ответ: Они делают одно и то же.

Правильный ответ: import { SomeType } ... может привести к тому, что весь модуль будет импортирован и включён в результирующий JavaScript, даже если это только тип. import type { SomeType } ... гарантирует, что импортируется только тип — на этапе компиляции, и никаких побочных эффектов или кода в output не будет.

Примеры реальных ошибок из-за незнания тонкостей темы


История

В крупном проекте команда импортировала типы через обычный импорт import { SomeType } ... из модуля с побочными эффектами (например, запускающий код при require/import). В результате в продакшн-сборку подтягивались лишние зависимости и side effect-ы, вызывая баги и увеличивая размер бандла.


История

Разработчик решил описать глобальный тип через глобальную переменную, а не через декларацию типа и случайно сделал экспорт типа и значения с одинаковыми именами. Это вызвало конфликт имён в ряде файлов и провал сборки после обновления TypeScript.


История

Команда не отличала особенности export/import type и экспортировала типы вместе с данными. В результате инструмент tree-shaking не смог исключить мёртвый код, увеличив bundle.