In this section, we will explore how TypeScript handles modularity and code organization through modules and namespaces. Understanding these concepts is crucial for writing maintainable and scalable TypeScript applications.

What are Modules?

Modules in TypeScript are a way to organize and encapsulate code. They allow you to split your code into smaller, reusable pieces. Each module can export classes, functions, variables, and interfaces to be used in other modules.

Key Concepts of Modules

  1. Exporting: Making code available to other modules.
  2. Importing: Bringing in code from other modules.
  3. Default Exports: A single export from a module.
  4. Named Exports: Multiple exports from a module.

Example of Modules

Exporting

// mathUtils.ts
export function add(a: number, b: number): number {
    return a + b;
}

export function subtract(a: number, b: number): number {
    return a - b;
}

Importing

// main.ts
import { add, subtract } from './mathUtils';

console.log(add(5, 3)); // Output: 8
console.log(subtract(5, 3)); // Output: 2

Default Export

// logger.ts
export default function log(message: string): void {
    console.log(message);
}

Importing Default Export

// main.ts
import log from './logger';

log('Hello, TypeScript!'); // Output: Hello, TypeScript!

What are Namespaces?

Namespaces are a way to group related code together under a single name. They are useful for organizing large codebases and avoiding name collisions.

Key Concepts of Namespaces

  1. Declaration: Defining a namespace.
  2. Nested Namespaces: Namespaces within namespaces.
  3. Accessing Members: Using the dot notation to access members of a namespace.

Example of Namespaces

Declaration

namespace Geometry {
    export function areaOfCircle(radius: number): number {
        return Math.PI * radius * radius;
    }

    export function areaOfRectangle(width: number, height: number): number {
        return width * height;
    }
}

Accessing Members

// main.ts
console.log(Geometry.areaOfCircle(5)); // Output: 78.53981633974483
console.log(Geometry.areaOfRectangle(10, 5)); // Output: 50

Nested Namespaces

namespace Geometry {
    export namespace Volume {
        export function volumeOfCube(side: number): number {
            return side * side * side;
        }

        export function volumeOfCylinder(radius: number, height: number): number {
            return Math.PI * radius * radius * height;
        }
    }
}

Accessing Nested Members

// main.ts
console.log(Geometry.Volume.volumeOfCube(3)); // Output: 27
console.log(Geometry.Volume.volumeOfCylinder(3, 5)); // Output: 141.3716694115407

Practical Exercises

Exercise 1: Create and Use a Module

  1. Create a file named stringUtils.ts.
  2. Export two functions: toUpperCase and toLowerCase.
  3. Import these functions in a file named main.ts and use them.

Solution

// stringUtils.ts
export function toUpperCase(str: string): string {
    return str.toUpperCase();
}

export function toLowerCase(str: string): string {
    return str.toLowerCase();
}

// main.ts
import { toUpperCase, toLowerCase } from './stringUtils';

console.log(toUpperCase('hello')); // Output: HELLO
console.log(toLowerCase('WORLD')); // Output: world

Exercise 2: Create and Use a Namespace

  1. Create a namespace named MathOperations.
  2. Add two functions: multiply and divide.
  3. Use these functions in a file named main.ts.

Solution

// mathOperations.ts
namespace MathOperations {
    export function multiply(a: number, b: number): number {
        return a * b;
    }

    export function divide(a: number, b: number): number {
        return a / b;
    }
}

// main.ts
/// <reference path="mathOperations.ts" />

console.log(MathOperations.multiply(6, 3)); // Output: 18
console.log(MathOperations.divide(6, 3)); // Output: 2

Common Mistakes and Tips

  • Common Mistake: Forgetting to use the export keyword in modules or namespaces.

    • Tip: Always ensure that the members you want to use outside the module or namespace are exported.
  • Common Mistake: Incorrectly importing default exports.

    • Tip: Remember that default exports do not use curly braces during import.
  • Common Mistake: Name collisions in large projects.

    • Tip: Use namespaces to group related functionalities and avoid name collisions.

Conclusion

In this section, we covered the basics of modules and namespaces in TypeScript. Modules help in organizing code into reusable pieces, while namespaces help in grouping related code together. Understanding these concepts is essential for writing clean, maintainable, and scalable TypeScript applications. In the next section, we will dive into decorators, which provide a way to add metadata to classes and methods.

© Copyright 2024. All rights reserved