Keeping all code in one file is rarely a good practice, and we know this is especially true when working with React.

However, if you have not yet worked with React, don’t worry, as the topic we’ll discuss about today is not directly tied to React but rather to TypeScript’s unique way of dealing with code split across multiple files using Modules.

The concept of Modules as a whole is not specific to TypeScript or any particular language; today, we will discuss about TypeScript’s way of handling those Modules (Which were introduced in the ES6 Specification of JavaScript).

What are Modules?

As previously referenced, Modules are used to split up code in multiple directories, subdirectories, and files within the same or different codebases.

If you are familiar with NPM and have worked with it before, you know that it references libraries as “modules” or “packages” based on ES6 Modules.

NPM is an excellent example of the ability to split code among different codebases.

To put it shortly: A module is a file that exports its own code.

The Syntax for Working With Modules

There are a couple of important keywords you’ll have to remember when working with Modules:

  • export
  • import
  • as
  • default

The export keyword

The export keyword is what we’ll need to use to export a module:

export const myFunction = (): void => {
  console.log('`MyFunction` has been invoked!`);
};

The snippet of code defined above will allow us to use the myFunction function in a lot of different places.

The import keyword

Using this second keyword, we will be able to import declarations from a specific module that we have previously defined using the export keyword:

import { myFunction } from './myFunction';

myFunction(); // Will log "`MyFunction` has been invoked!" to the console.

You may notice that the import has been done with the help of a pair of curly braces ({}), as well as a new from keyword.

The curly braces ({}) will contain the names of the named exports (export will grant us access to any exported member as a named export), while the from keyword will be followed by the location of the module we wish to import from (In our case, both files are in the same directory).

The as keyword

There will be scenarios, however, where we might want to change the name of a named export member in the file where we wish to import that specific member.

In this case, we will have to make use of the as keyword, which allows us to change the name that a named import will hold in our file:

import { myFunction as myFunc } from './myFunction';

myFunc(); // It will work the same as if we were to use the declaration name (`MyFunction`)

This will also allow us to import the same member multiple times in the same file using different names:

import {
  myFunction as myFunc,
  myFunction as mySecondFunc,
  myFunction as myThirdFunc,
  myFunction
} from './MyFunction';

myFunc(); // Will log "`MyFunction` has been invoked!" to the console.
mySecondFunc(); // Will log "`MyFunction` has been invoked!" to the console.
myThirdFunc(); // Will log "`MyFunction` has been invoked!" to the console.
myFunction(); // Will log "`MyFunction` has been invoked!" to the console.

The default keyword

Apart from the named exports, we can also simultaneously have a single default exported member.

const myMainFunction = (): void => {
  console.log('`myMainFunction` has been invoked!');
};

export const mySecondaryFunction = (): void => {
  console.log('`mySecondaryFunction` has been invoked!');
}:

export default myMainFunction;

Notice that we cannot simultaneously have both a const variable declaration and a default export declaration. This, however, is not the case for function and class declarations.

We would import our previously defined arrow functions as such:

import myDefaultExport, { mySecondaryFunction } from './myFunctions';

myDefaultExport(); // Will log "`myMainFunction` has been invoked!" to the console.

mySecondaryFunction(); // Will log "`mySecondaryFunction` has been invoked!" to the console.

Unlike named exports, we can import our default exported member under whichever name we wish to use in our main file.

In the example above, we’ve imported the myMainFunction as myDefaultExport.

Summary

We reviewed the critical aspects of Modules in TypeScript, the magic keywords, and what they mean.

As a bonus, I will also attach a Cheat Sheet for Modules below, which Samantha Ming has created:

I hope you have enjoyed the read and got a better understanding of what Modules are in TypeScript, how we use it, and how we learn about other specifics of them.

Feel free to leave your thoughts on this article below! 👇

Cheers!

👋 Hey, I'm Vlad Mihet
I'm Vlad Mihet, a blogger & Full-Stack Engineer who loves teaching others and helping small businesses develop and improve their technical solutions & digital presence.

💬 Leave a comment

Your email address will not be published. Required fields are marked *

We will never share your email with anyone else.