Exporting and Importing page
Learn how to export and import values from a file.
Overview
In this section, you will:
- Export values from a file
- Import values from another file
- Learn why named exports are preferred over default exports
- Learn how to import and export functions between modules
Objective 1: Export and import values
A fundamental part of writing code is creating values that you can use across multiple files. This allows for modular, maintainable, and scalable code. Let’s break down how to export and import values in TypeScript.
In TypeScript, you can export any type of value: variables, functions, classes, interfaces, etc.
There are two types of exports: default exports and named exports.
Default exports
Imagine we have a config.ts
file:
const config = {
name: "Bitovi Academy",
url: "https://www.bitovi.com/academy/",
};
export default config;
In the example above, we create a config
variable and then use export default
to export it.
Then, we could consume the value in another file:
import appConfig from "./config.ts";
const appName = appConfig.name;
In the code above, the appConfig
variable is the same as the config
variable exported from config.ts
.
Note that the appConfig
variable name does not need to match the name in the file that has the export
.
Named exports
Named exports are called that because there is an explicit name in the file with the export
.
Let’s imagine we have a helpers.ts
file:
function clampNumber(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max);
}
export {
constrain: clampNumber,
};
In the example above, we export a constrain
function from our helpers.ts
file. Note that the local function name is called something else (clampNumber
) and we export it with a specific name (constrain
).
We can import the constrain
function like so:
import { constrain } from "./helpers.ts";
const constrained = constrain(-18, 0, 100);
In the code above, we can import the constrain
function by name from helpers.ts
and use it in our code.
Shorthand
If the name of the function in the file matches what you want to export it as, you can use this shorthand in your export statement:
function constrain(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max);
}
export {
constrain,
};
Exporting in place
You can also export values from where they’re declared in the file, without a separate export
statement:
export function constrain(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max);
}
Default exports vs. named exports
While you can use both in projects and some APIs may require you to use one type of export vs. the other, we recommend you use named exports in all of the code you write.
Here’s why:
Consistency: Named exports enforce consistency. The name of the export has to be used wherever it's imported unless explicitly renamed. This consistency makes it easier to trace through code and understand what is being imported and used.
Explicitness and clarity: Since you have to explicitly list what you are importing, it provides a clear overview of what dependencies a module has. This explicitness improves readability and maintainability of the code.
Better tooling support: Many IDEs and tools have easier times with auto-completion and refactoring when using named exports. This can lead to more efficient coding and a lower chance of errors.
Setup
✏️ Create src/exporting-and-importing/exporter.ts and update it to be:
function greeter(person: string) {
return "Hello, " + person;
}
// Exercise: export greeter
✏️ Create src/exporting-and-importing/importer.ts and update it to be:
// Exercise: import greeter
export default function () {
return greeter("Earth");
}
Verify
✏️ Create src/exporting-and-importing/importer.test.ts and update it to be:
import assert from 'node:assert';
import { describe, it } from 'node:test';
import getMessageWithGreeting from "./importer";
describe('Importer', () => {
it('should return a greeting', () => {
const message = getMessageWithGreeting();
assert.strictEqual(message, "Hello, Earth", "message should be correct");
});
});
✏️ Update package.json to be:
{
"name": "learn-typescript",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "node --require ts-node/register --test src/**/**.test.**"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"ts-node": "^10.9.2",
"typescript": "~5.4"
}
}
Exercise
Use your knowledge of named exports and imports to do the following:
- Export
greeter
fromexporter.ts
- Import
greeter
inimporter.ts
Having issues with your local setup? You can use either StackBlitz or CodeSandbox to do this exercise in an online code editor.
Solution
If you’ve implemented the solution correctly, the tests will pass when you run npm test
!
Click to see the solution
✏️ Update src/exporting-and-importing/exporter.ts to be:
function greeter(person: string) {
return "Hello, " + person;
}
export {
greeter,
};
✏️ Update src/exporting-and-importing/importer.ts to be:
import { greeter } from "./exporter"
export default function () {
return greeter("Earth");
}
Having issues with your local setup? See the solution in StackBlitz or CodeSandbox.
Bonus exploration
- Hover over
greeter
, what does your IDE show? - Pass a number to
greeter
, what does your IDE show?
Next steps
Next, let’s learn how to declare types in TypeScript.