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もサポートされており、これにより最終的なバンドルにコードを引き込むことなく、型のみをインポートすることができます。これによりビルドが最適化されます:
import type { User } from './types';
重要な特徴: TypeScriptでは、最終的なJavaScriptに含まれない型のみをエクスポートすることができます。
import { SomeType } from './file'とimport type { SomeType } from './file'の違いは何か?
間違った回答: どちらも同じことを行います。
正しい回答: import { SomeType } ...は、型だけでもモジュール全体がインポートされ、結果としてJavaScriptに含まれる可能性があります。import type { SomeType } ...は、型のみがインポートされることを保証し、コンパイル時に副作用や出力のコードがないことを確実にします。
物語
大規模プロジェクトでチームが副作用のあるモジュールから
import { SomeType } ...で型をインポートしました(たとえば、require/import時にコードを実行するもの)。その結果、プロダクションビルドに不要な依存関係と副作用が持ち込まれ、バグが発生し、バンドルのサイズが増加しました。
物語
開発者がグローバル変数を通じてグローバル型を記述することを決定し、型宣言ではなく、偶然に同じ名前の型と値をエクスポートしました。これにより、いくつかのファイルで名前の衝突が発生し、TypeScriptの更新後にビルドが失敗しました。
物語
チームはexport/import typeの特徴を区別せずに、データと一緒に型をエクスポートしました。その結果、tree-shakingツールが死んだコードを除外できず、バンドルが増加しました。