TypeScript supports both main JavaScript module systems — CommonJS and ES Modules, allowing the use of the import and export keywords to organize code. The distinction of TypeScript is the presence of type declarations, which can be exported and imported just like values.
For example, you can export an interface:
// 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 are also supported, allowing for the import of only types without pulling in code into the final bundle, optimizing the build process:
import type { User } from './types';
An important feature: in TypeScript, you can only export types that will not appear in the final JavaScript.
What is the difference between
import { SomeType } from './file'andimport type { SomeType } from './file'?
Wrong answer: They do the same thing.
Correct answer: import { SomeType } ... may cause the entire module to be imported and included in the resulting JavaScript, even if it is only a type. import type { SomeType } ... ensures that only the type is imported — at compile time, leading to no side effects or code in the output.
Story
In a large project, the team imported types via a regular import
import { SomeType } ...from a module with side effects (for example, executing code upon require/import). As a result, unnecessary dependencies and side effects were pulled into the production build, causing bugs and increasing the bundle size.
Story
A developer decided to describe a global type through a global variable rather than through a type declaration and accidentally exported a type and a value with the same names. This caused name conflicts in several files and resulted in a build failure after updating TypeScript.
Story
The team did not distinguish the nuances of export/import type and exported types along with data. As a result, the tree-shaking tool could not exclude dead code, increasing the bundle.