A Handy Guide to Export and Import Modules for JavaScript and TypeScript

ECMAScript is a scripting-language specification standardized by Ecma International in ECMA-262 and ISO/IEC 16262. JavaScript is one of the most popular implementations of ECMAScript. Starting from the first edition in June 1997, JavaScript has evolved to provide more functionality and become easier to use. ES6 or ES2015 is a revolutionary version. It adds a significant amount of new syntaxes for writing complex applications. One of the prominent additions is modules.

An ES6 module is a JavaScript file. It is executed within its own scope — not in the global scope. Variables, functions, and classes that are declared in a module are not sharable between modules unless they are explicitly exported and imported.
  • export: A statement to export primitive values, objects, functions, or classes from the module for the purpose of being used by other modules.
  • import: A statement to use primitive values, objects, functions, or classes that are exported from another module. Typically, an import is static, but it can be dynamic too.

TypeScript has also adopted ES6 modules. There are more things to export and import, such as interfaces, types, namespaces, and enums.

Exports and imports are closely connected. We will give some examples below to see how to write export and import statements.

Export and Import Statements: Example 1

Variables can be exported individually via putting export in front of each declaration.
export let a, b, c, d, e, f, g, h;
export let i, j, k, l, m, n, o, p;
export let q;a = 1; // a primitive value of number
b = null; // a primitive value of null
c = undefined; // a primitive value of undefined
d = Symbol(); // a primitive value of Symbol
e = [1, 2, 3]; // an arrayf = { // a plain object
a: 1,
b: 2,
c: 3
};g = Date; // a Date object
h = new Map(); // a Map object
i = new Set(); // a Set objectj = new Promise((resolve) => { // a Promise object
resolve(5);
});k = function() { // an anonymous function
};l = function myFunction () { // a named function
};m = () => true; // an arrow functionn = function* myGenerator(i) { // a generator function
yield i;
}o = async function myAsync() { // an async function
await n;
}p = class { // a class with no class name
};q = class MyClass { // a class with a class name
};
These exports can be selectively imported by specifying variable names:
import { a, b, c } from './myExports';
----------------------- or ---------------------
import { k } from './myExports';
----------------------- or ---------------------
import { a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q } from './myExports';
With many import items, there is an option to import the whole thing as a module and then use the module name.

For the following import statement, everything is imported as myImportModule:
import * as myImportModule from './myExports';
Then the code can use the exported items as myImportModule.a, myImportModule.b, etc.

Export and Import Statements: Example 2

Variables can be exported individually via putting export in front of each declaration with a value assignment.
export var a = 1; // It is recommended to use let or const
// var is kept for backwards compatibility
export let b = null; // a variable initialized to null
export const c = undefined; // a constant variable
These exports can be imported as follows:
import { a, b, c } from './myExports';
Export and Import Statements: Example 3

Function and class definitions can be exported directly by putting export in front of their definitions.
export function myFunction() {}
export class myClass {}
These exports can be imported as follows:
import { myFunction, myClass } from './myExports';
In addition, TypeScript supports exporting types, interfaces, and enums.
export type NumberOrString = number | string; // a type example, union is supported by type, but not by interfaceexport interface Base {} // a base interface exampleexport interface Child extends Base {} // an extended interface example, inheritance is supported by interface, not by typeexport enum DayOfWeek { // an enum example
Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
}
These exports can be imported as follows:
import { NumberOrString, Base, Child, DayOfWeek } from './myExports';
TypeScript has export = syntax. It specifies a single object that is exported from the module. This can be a function, class, interface, namespace, or enum. The following is how React is being exported by DefinitelyType.
export = React;
export as namespace React;
Export and Import Statements: Example 4

Variables can be exported as a list.
const dayDefinitions = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const daysOfWeek = dayDefinitions.length;
let currentDayIndex = 3;
export { dayDefinitions, daysOfWeek, currentDayIndex };
These exports can be imported as follows:
import { dayDefinitions, daysOfWeek, currentDayIndex } from './myExports';
Export and Import Statements: Example 5

Variables can be exported as a list. In addition, items on the list can be renamed. The new name is also called an alias.
const a = 1, c = undefined;
let b = null;
export { a as NUMBER_ONE, b as newNameForB, c as undefined_value};
These exports can be imported as follows:
import { NUMBER_ONE, newNameForB, undefined_value } from './myExports';
In addition, an importer can rename the item with a new alias. Here is an example of an alias of an alias:
import { NUMBER_ONE as myA, newNameForB as myB, undefined_value as myC} from './myExports';
Export and Import Statements: Example 6

Destructure assignments can be used for export too. In addition, these kinds of exports can be selectively renamed.
let person1 = {
name: 'John',
age: 10,
grade: 5
};let person2 = ['Lisa', 12, 7];// name is renamed to nameOfPerson1
// age is renamed to ageOfPerson1
export const { name: nameOfPerson1, age: ageOfPerson1 } = person1;// first item is renamed to nameOfPerson2
// second item is renamed to ageOfPerson2
export const [ nameOfPerson2, ageOfPerson2 ] = person2;
These exports can be imported as follows:
import { nameOfPerson1, ageOfPerson1, nameOfPerson2, ageOfPerson2 } from './myExports';
Export and Import Statements: Example 7

There are two types of exports: default exports and named exports. Each module can have at most one default export in a module, but it can have multiple named exports.

Only expressions, functions, or classes are allowed to be a default export. The name of a default export is not required.

From examples 1 through 6, all exports are named export. Here, we’ll look at some examples of a default export.
export default 5;
----------------------- or ---------------------
const a = 5;
export { a as default };
----------------------- or ---------------------
const a = 5;
export default a;
----------------------- or ---------------------
let a;
export default a = 5;
----------------------- or ---------------------
export default function() {};
----------------------- or ---------------------
export default class {};
When a default export is imported, the importer can name it anything.
import { default as X } from './myExports';
----------------------- or ---------------------
import X from './myExports';


Does the following line look familiar?import React from 'react';


In fact, importing a default export and other items can be mixed. Is the following another familiar line?import React, { useCallback, useState, useEffect } from 'react';


Examples of Re-Exporting

Modules can be exported or partially re-exported by a new module.
export * from './myExports'; // re-export everything
export {myFunction} from './myExports'; // partial re-export
Re-exporting aggregates all export statements together into a new module as a single source.

If we have a reExports.js defined as follows:
export { a, b, c, d } from './myExports1';
export { e, f } from './myExports2';
export { g, h, i} from './myExports3';
It can be imported neatly as:
import { a, b, c, d, e, f, g, h, i } from './reExports';
Re-exporting works for both JavaScript and TypeScript.

A small quiz to finish things off: Do you know why the following code complains that myFunction is not defined?
export {myFunction} from './myExports';
myFunction();
It is because the re-export statement does not make it imported locally. The following code would fix the issue:
import {myFunction} from './myExports';
export {myFunction} from './myExports';
myFunction();
Thanks for reading. I hope this was helpful. If you have any questions, feel free to leave a response. You can see my other Medium publications here.

WRITTEN BY

Jennifer Fu
Post a Comment