TypeScript: Type-Only Imports and Exports
Use `import type` to tell the compiler an import is only for type-checking and should be erased from the final JavaScript. This prevents tools like Babel from generating unwanted runtime code when compiling files in isolation.
WHY IT EXISTS TypeScript's compiler is smart enough to erase imports that are only used for types. However, some build tools like Babel or esbuild compile each file in isolation (transpilation). They can't always know if an import is a type or a runtime value without a full program analysis, which can lead to keeping unnecessary imports in the final JavaScript. import type makes the developer's intent explicit, solving this ambiguity.
THE MENTAL MODEL Think of import type as a direct command to the compiler: "This import is for static type-checking only. Under no circumstances should it exist in the compiled JavaScript." It creates a hard boundary between the world of types, which disappear after compilation, and the world of values, which exist at runtime.
HOW IT WORKS You add the type keyword immediately after the import or export keyword. For example: import type { User } from './types';. The TypeScript compiler will use the User type for annotations and static analysis, but when it generates the corresponding JavaScript file, that import line will be completely removed. This guarantees zero runtime overhead. The same logic applies to export type { SomeThing }.
WHEN TO USE IT Use import type when you are certain you are only importing type declarations (like interfaces, type aliases). It is especially important in projects that set the isolatedModules compiler option to true, which is common practice with modern bundlers. It also serves as clear documentation to other developers that a particular import has no runtime side effects.
WHEN NOT TO USE IT Do not use import type for anything that has a runtime value. The most common mistake is importing a class you intend to extend or instantiate. A class is both a type (for annotations) and a value (the constructor function at runtime). Using import type { Component } from 'react' and then trying class MyComponent extends Component will fail because Component was imported as a type only, not a value you can extend.
ONE CANONICAL EXAMPLE Imagine a file api-types.ts that defines data structures: export type Product = { id: number; name: string; };. In a component file, you might use this type for props: import type { Product } from './api-types'; function displayProduct(item: Product) { console.log(item.name); }. The import type statement ensures that no require('./api-types') or ES module import is generated in the output JavaScript, because the Product type is erased after checking is complete.
Read the original → typescriptlang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.