Modules in TypeScript
This article explains modules in TypeScript.
YouTube Video
Modules in TypeScript
Modules in TypeScript are an important feature for enhancing code reusability and maintainability. Like JavaScript, TypeScript is also based on the ECMAScript 2015 (ES6) module system, but a key feature is the ability to leverage TypeScript's type system.
What are Modules?
A module is a system for grouping related code into a single unit that can be imported and reused in other files. In TypeScript, a scope is created per file to encapsulate the code, preventing it from affecting other files. This helps avoid code collisions and makes maintenance easier.
Internal and External Modules
- Internal Modules (Namespaces): A module definition method used in TypeScript 1.5 and earlier, now not recommended. It is now treated as a 'namespace.'.
- External Modules: The current standard, based on the ES6 module system. This section mainly explains external modules.
How to Export Modules
When creating modules, exporting is necessary to allow access from outside. In TypeScript, you can export values, functions, classes, etc. using the export
keyword. There are mainly two types of exports.
Named Exports
Used for making multiple exports, allowing the import side to select and use specific ones.
1// mathUtils.ts
2export const pi: number = 3.14159;
3
4export function add(x: number, y: number): number {
5 return x + y;
6}
7
8export function subtract(x: number, y: number): number {
9 return x - y;
10}
Default Exports
Used when you want the entire module to have a single default export. Default exports are exported without a name, allowing the import side to receive them with any name.
1// calculator.ts
2export default class Calculator {
3 add(x: number, y: number): number {
4 return x + y;
5 }
6
7 subtract(x: number, y: number): number {
8 return x - y;
9 }
10}
How to Import Modules
To use modules, you import values, functions, classes, etc. from within the module using the import
keyword.
Named Imports
When importing specific elements from a named export, use curly braces {}
.
1// main.ts
2import { pi, add, subtract } from './mathUtils';
3
4console.log(`Value of pi: ${pi}`);
5console.log(`Addition: ${add(10, 5)}`);
6console.log(`Subtraction: ${subtract(10, 5)}`);
Default Imports
When importing a default export, you can receive it with any name.
1// main.ts
2import Calculator from './calculator';
3
4const calculator = new Calculator();
5console.log(`Addition: ${calculator.add(10, 5)}`);
6console.log(`Subtraction: ${calculator.subtract(10, 5)}`);
Import Aliases
To avoid name collisions or shorten long names, you can import with an alias.
1// main.ts
2import { add as addition, subtract as subtraction } from './mathUtils';
3
4console.log(`Addition: ${addition(10, 5)}`);
5console.log(`Subtraction: ${subtraction(10, 5)}`);
Difference Between Modules and Namespaces
A namespace (namespace
) is an internal module structure used in early TypeScript to group code together. However, ES6 modules are now recommended, and namespaces are rarely necessary.
Namespaces can be defined within the same file or across multiple files, and because they can be globally expanded, managing dependencies can become difficult. In contrast, modules have separate scopes per file and have clear dependencies, making them a more modern and secure method.
1// Example of a namespace
2namespace Geometry {
3 export function calculateArea(radius: number): number {
4 return Math.PI * radius * radius;
5 }
6}
7
8// Can be used directly without importing the module (not recommended)
9const area: number = Geometry.calculateArea(5);
10console.log(`Area: ${area}`);
TypeScript Module Resolution
In TypeScript, there are two strategies for module resolution.
- Node Module Resolution: The standard resolution method used in Node.js environments that resolves modules by searching within the
node_modules
folder. - Classic Module Resolution: TypeScript's own resolution method that performs more flexible searching, but is not commonly used nowadays.
Typically, Node module resolution is used and is enabled by default unless specified otherwise in the configuration file.
Practical Example
Finally, an example is shown of implementing and reusing computational functions using modules.
mathUtils.ts
1export const pi: number = 3.14159;
2
3export function multiply(x: number, y: number): number {
4 return x * y;
5}
6
7export function divide(x: number, y: number): number {
8 if (y === 0) {
9 throw new Error("Cannot divide by zero");
10 }
11 return x / y;
12}
- This file defines mathematical utility functions and provides reusable basic arithmetic operations.
calculator.ts
1import { multiply, divide } from './mathUtils';
2
3export default class Calculator {
4 multiplyNumbers(x: number, y: number): number {
5 return multiply(x, y);
6 }
7
8 divideNumbers(x: number, y: number): number {
9 return divide(x, y);
10 }
11}
- This file defines and exports the
Calculator
class. It encapsulates calculator functionality internally using functions imported frommathUtils
.
main.ts
1import Calculator from './calculator';
2
3const calculator = new Calculator();
4
5const result1: number = calculator.multiplyNumbers(10, 5);
6console.log(`Multiplication: ${result1}`);
7
8const result2: number = calculator.divideNumbers(10, 2);
9console.log(`Division: ${result2}`);
- This file is the entry point of the application. It creates an instance of the
Calculator
class, performs multiplication and division, and logs the results to the console.
Summary
The TypeScript module system is a powerful tool for organizing code, enhancing reusability, and increasing maintainability. The use of external modules based on ES6 modules is recommended, and using export
and import
keywords allows for easy exporting and importing of modules.
You can follow along with the above article using Visual Studio Code on our YouTube channel. Please also check out the YouTube channel.