YouTip LogoYouTip

Ts Module

TypeScript Modules

TypeScript Modules

The module system is the foundation of modern TypeScript development.

TypeScript fully supports ES Module syntax and provides rich module resolution strategies.

Through the module system, code can be split into reusable units, enabling code organization and reuse.


Why Do We Need a Module System?

As project scale grows, the amount of code increases.

Scattering code across multiple files and organizing it with modules improves code maintainability and reusability.

The module system gives each file its own scope, avoiding global variable pollution.

Concept Explanation: A module is a TypeScript file containing export and import statements. Content is exported using export and imported using import.

Module Exports

Use the export keyword to export variables, functions, classes, interfaces, etc., for use by other modules.

user.ts Module

// Exporting variables
export var name = "Alice";
export const age = 25;

// Exporting a function
export function greet(message: string): string {
    return "Hello, " + message;
}

// Exporting a class
export class User {
    // Constructor parameter property
    constructor(public name: string) {}

    // Self-introduction method
    introduce(): string {
        return "I am " + this.name;
    }
}

// Exporting an interface (interfaces disappear after compilation, used only for type checking)
export interface Config {
    // Configure host
    host: string;
    // Configure port
    port: number;
}

// Batch export: Renaming exports
export { name as userName, age as userAge };
Note: Interfaces and types do not produce actual code in the compiled JavaScript; they are used only for TypeScript's type checking.

Module Imports

Use the import keyword to import exported content from other modules.

main.ts Importing Modules

// Named import: Import specific content from a module
import { name, age, greet } from "./user";

// Default import: Import the default export of a module
import User from "./user";

// Namespace import: Place all exports of a module into an object
import * as UserModule from "./user";

// Renamed import: Avoid naming conflicts
import { greet as sayHello } from "./user";

// Using imported content
console.log(greet("World"));
console.log(sayHello("TypeScript"));

Output:

Hello, World
Hello, TypeScript
Path Explanation: Import paths can be relative (e.g., ./user) or absolute (e.g., @/utils).

Default Exports

Each module can have one default export.

Default exports do not require curly braces when imported and can be given any name.

math.ts Module

// Default export: A module can only have one default export
export default function add(a: number, b: number): number {
    return a + b;
}

// Can be mixed with other exports
export function multiply(a: number, b: number): number {
    return a * b;
}

main.ts Import

// Import default export: Can be given any name
import add from "./math";

// Import named export: Requires curly braces
import { multiply } from "./math";

console.log("Addition: " + add(2, 3));
console.log("Multiplication: " + multiply(4, 5));

Output:

Addition: 5
Multiplication: 20
Suggestion: Use default exports for primary content like utility functions and classes, and named exports for auxiliary functions and interfaces.

Re-exports

Re-exports are used to aggregate content from multiple modules or expose a module's exports to another module.

index.ts Aggregation Module

// Re-export specific content from other modules
export { name, age } from "./user";

// Re-export default export (requires renaming)
export { default as User } from "./user";

// Re-export everything
export * from "./math";
Application Scenario: Use index.ts as an entry file to centrally export submodule content for convenient unified imports.

Module Resolution Strategies

TypeScript provides multiple module resolution strategies for finding imported modules.

These can be configured in tsconfig.json.

tsconfig.json Configuration

{
    "compilerOptions": {
        // Node resolution strategy
        // Follows Node.js module resolution rules
        "moduleResolution": "node",

        // Classic resolution strategy
        // Strategy used in earlier versions of TypeScript
        "moduleResolution": "classic",

        // base URL: Set base path
        // All non-relative path imports are resolved based on this path
        "baseUrl": "./src",

        // Path mapping: Set aliases for import paths
        "paths": {
            // Imports starting with @ map to the src directory
            "@/*": ["./*"],
            // Imports starting with @components map to the components directory
            "@components/*": ["./components/*"]
        }
    }
}
Configuration Suggestion: For new projects, the Node resolution strategy is recommended as it is currently the most commonly used method.

Dynamic Imports

Dynamic imports use the import() syntax to load modules on-demand at runtime.

This is very useful for code splitting and lazy loading.

Example

// Dynamic import - Lazy loading
// import() returns a Promise
async function loadMath() {
    // Dynamically import the module; it will only load when this line is executed
    const math = await import("./math");
    // math.default is the default exported function
    console.log("Dynamic addition: " + math.default(1, 2));
}

// Call the lazy loading function
loadMath();

// Conditional import: Dynamically load different modules based on conditions
async function loadFeature(enable: boolean) {
    if (enable) {
        // Only load the module if the condition is met
        const feature = await import("./feature");
        feature.run();
    }
}

// Load based on condition
loadFeature(true);

Output:

Dynamic addition: 3
Performance Optimization: Dynamic imports enable code splitting, loading additional code only when needed, reducing initial load time.

Important Notes

  • Relative Paths: Use relative paths to import local modules (./, ../)
  • Module Extensions: TypeScript automatically handles extensions during compilation
  • Default vs. Named: One default export per module, multiple named exports
  • esModuleInterop: Enable this option for easier importing of CommonJS modules
Best Practice: Keep import paths consistent, use path aliases to simplify long paths, and establish a clear module organization structure.

Summary

The module system is the core of TypeScript project organization.

  • export: Export variables, functions, classes, interfaces
  • import: Import exported content
  • Default Export: One per module, flexible to use
  • Re-export: Aggregate modules, create entry files
  • Dynamic Import: Lazy loading, optimize performance
  • Module Resolution: Configure path aliases and resolution strategies
Suggestion: Organize module structure reasonably, use path aliases to simplify imports, and establish clear export/import conventions.
← Func Date Interval FormatTs Object β†’