Introduction to TypeScript modules

Web sites are turning into very complex applications, and the code complexity increases. You need to track the dependencies between JS files and includes them in the right order, otherwise the website won't work. Testing is also more complicated as the application grows.

Modules helps you segmenting your application. Indeed, modules allows you to create small units of independent and reusable code. Plus, modules know their dependencies, so they can load them when needed in the right order. Let's see how to use modules in TypeScript!

How to use modules in TypeScript?

In TypeScript, a module is a file containing values, functions or classes. You can make some of them public, i.e. visible from other modules, by exporting them. Non exported objects are private. Let's create a very simple math module with a single exported function!

First, create a file named math.ts:

// public because of the export keyword
export function add(a: number, b: number): number {
    log(`${a} + ${b}`);
    return a + b;
}

// private
function log(message: string): void {
    console.log(message);
}

Then, you can consume the math module from another module. The import keyword allows to use the exported functions of a module. In this case we want to use the add function from the math module. Let's create a new file named main.ts:

// We want to use the add function from the math module
import { add } from "./math";

// Use the add function as if it was in the global context
console.log(add(1, 2));

If you want to use all the exported functions of a module, you can use the * syntax:

// Import the math module as a *namespace*
import * as math from "./math";

// Use the add function in the namespace math
console.log(math.add(1, 2));

// math.log(""); // error: log is not exported

You'll find the complete syntax in the documentation: https://www.typescriptlang.org/docs/handbook/modules.html

How to include the JS files in the HTML page?

You now know how to create a module in TypeScript, but how to use them in your html files.

There are many module formats with advantages and disavantages: AMD, CommonJS, UMD, System and the native ES6 modules. TypeScript supports all of them, so it's all up to you. The ES6 format is not well supported by the browsers yet, so you should use another format. In this post I'll use SystemJS as it is popular.

First, you need to configure TypeScript to output this format. Open the tsconfig.json file and set the following line:

{
    "compilerOptions": {
        "module": "system"
    }
}

Then, add SystemJS to your page. You can get it from cdnjs:

<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.20.19/system.js" integrity="sha256-HCJlhCZ21EKx0Wo6wCF+rbeBHlVlOSJccd4zTQe2TNw=" crossorigin="anonymous"></script>

Finally, instruct SystemJS to load your main module. By default, when SystemJS needs to download a file, it uses the name of the module (i.e. the name used in the import statement). In our case, the name of the module is not the name of the file. We need to add the suffix .js to the module name. We can configure SystemJS to do it automatically:

<script>
// Instruct SystemJS to add the js extension to the module name to compute the final file name
System.config({
    packages: {
        './': {
            defaultExtension: 'js'
        }
    }
});

// Load the main module
SystemJS.import("main");
</script>

If you open the web page, you should see the following output in the console:

And in the network tab, you should see the main.js and math.js are downloaded while they are not directly included in the page. The dependencies are downloaded automatically by SystemJS, so you don't need to manage them anymore:

Conclusion

It's very simple to start using modules with TypeScript and SystemJS! Modules will help you in releasing cleaner applications, and in understanding the dependencies between the components. While native modules are not well supported yet, you can use modules with SystemJS or requireJS now and migrate to native modules once the support will be better.