When to use Type Only Imports Exports in TypeScript?
Since the introduction of type-only imports in TypeScript 3.8, a lot of developers including me have been confused about the usage of type-only imports. If we read the official docs, it says -
import type
only imports declarations to be used for type annotations and declarations. It always gets fully erased, so there’s no remnant of it at runtime.Similarly,
export type
only provides an export that can be used for type contexts, and is also erased from TypeScript’s output.
But isn't typescript code supposed to cease automatically at runtime? Why do we need type-only imports?
To understand this, First, we need to understand how single-file transpilers (like Babel) work.
Suppose we have the following 3 files -
Component.tsx
import { Props } from "./types"; const Component = (props: Props) => { return <div>Component</div>; }; export { Component };
types.ts
export type Props = { a: number; b: string; };
index.ts
import { Component } from "./Component"; import { Props } from "./types"; export { Component, Props };
Now, let's see what will the corresponding output JS files look like when they are passed through a single file transpiler -
Component.js
"use strict"; exports.__esModule = true; exports.Component = void 0; var Component = function (props) { return <div>Component</div>; }; exports.Component = Component;
types.js
"use strict"; exports.__esModule = true;
index.js
"use strict"; exports.__esModule = true; exports.Props = exports.Component = void 0; var Component_1 = require("./Component"); exports.Component = Component_1.Component; var types_1 = require("./types"); exports.Props = types_1.Props;
If we compare the above outputs, we can see that all the typescript-only code (types and imports) has been successfully removed in Component.tsx
and types.ts
file but not in index.js
file.
If we run this JS code, we will get a runtime error ❗️ since there is no named export Props
in types.js
file
Now, let's see how our transpiler was able to remove typescript-only code in each of the files -
Component.tsx
- Here, the importProps
is being used as atype
in the file itself, So it is able to deduce thatProps
is indeed a type and can safely remove it.import { Props } from "./types"; 👇 const Component = (props: Props) => {
types.ts
- In this file, we have used thetype
keyword to declareProps
type. So, it can also be safely removed.👇 export type Props = {
index.ts
- In this file, we are simply importing and re-exportingComponent
andProps
. Since single-file transpilers work only on a single file at a time, there is no way to know whether these are types or variables or functions, etc.So, they both are kept in the output js file.
import { Component } from "./Component"; import { Props } from "./types"; ❔❔❔ export { Component, Props };
To fix this, we can mark Props
import as type-only
-
import { Component } from "./Component";
import type { Props } from "./types";
export { Component, Props };
Now, our transpiler knows for sure that Props
is a type and can safely omit it.
Note: This problem only occurs when we are using a single file transpiler such as babel since they only operate on a single file at a time and can't apply code transforms that depend on understanding the full type system.
TypeScript also provides us with a flag isolatedModules
to avoid writing certain code (like the above) that can cause issues when using a single-file transpiler.
If we turn on the isolatedModules
flag, we will get the following error in index.ts
file
import { Component } from "./Component";
import { Props } from "./types";
// ❗️❗️ Re-exporting a type when the '--isolatedModules' flag is provided requires using 'export type'. ❗️❗️
export { Component, Props };
So, to summarize this 🔖-
If we are importing a
type
and using it in the same file, we do not need to usetype
since even a single file transpiler can understand from the context that it is atype
.But, If we are only exporting the
type
and not using it, we need to make it atype-only
import to explicitly tell the transpiler that it is a type.We should turn on the
isolatedModules
flag to avoid such issues.
Subscribe to my newsletter
Read articles from Anmol Kansal directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Anmol Kansal
Anmol Kansal
Web Development allows me to bring my ideas to life. Passionate about Web Development and Proficient in Data Structures and Algorithms, I like to solve challenging problems.