TypeScript Module System
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.
SVG Diagram: Module Export/Import
Why Do We Need a Module System
As project scale grows, the amount of code increases.
Distributing code across multiple files and organizing it through modules improves code maintainability and reusability.
The module system gives each file its own scope, preventing global variable pollution.
Concept Explanation:A module is a TypeScript file that contains export and import statements. Content is exported via export and imported via import.
Module Export
Use the export keyword to export variables, functions, classes, interfaces, etc. for use by other modules.
user.ts Module
export var name = "Alice";
export const age = 25;
// Export function
export function greet(message: string): string {
return "Hello, " + message;
}
// Export class
export class User {
// Constructor parameter properties
constructor(public name: string) {}
// Self-introduction method
introduce(): string {
return "I am " + this.name;
}
}
// Export interface (interfaces disappear after compilation; only used for type checking)
export interface Config {
// Configure host
host: string;
// Configure port
port: number;
}
// Batch export: rename exports
export { name as userName, age as userAge };
Note:Interfaces and types do not generate actual code in compiled JavaScript; they are only used for TypeScript type checking.
Module Import
Use the import keyword to import exported content from other modules.
main.ts Importing Module
import { name, age, greet } from "./user";
// Default import: import a module's default export
import User from "./user";
// Import all: put all module exports into an object
import * as UserModule from "./user";
// Rename import: avoid naming conflicts
import { greet as sayHello } from "./user";
// Use imported content
console.log(greet("World"));
console.log(sayHello("TypeScript"));
Output:
Hello, World Hello, TypeScript
Path Explanation:Import paths can be relative paths (e.g.,
./user) or absolute paths (e.g.,@/utils)。
Default Export
Each module can have one default export.
Default exports do not require curly braces when importing and can be given any name.
math.ts Module
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 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:
加法: 5 乘法: 20
Recommendation:Use default exports for main export content such as utility functions and classes; use named exports for helper functions, interfaces, etc.
Re-export
Re-export is used to aggregate content from multiple modules or expose one module's exports to another module.
index.ts Aggregating Module
export { name, age } from "./user";
// Re-export default export (requires renaming)
export { default as User } from "./user";
// Re-export all content
export * from "./math";
Use Cases:Use index.ts as an entry file to centrally export child module content for unified imports.
Module Resolution Strategies
TypeScript provides multiple module resolution strategies for locating imported modules.
This 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 by early versions of TypeScript
"moduleResolution": "classic",
// base URL: sets the base path
// All non-relative path imports are resolved based on this path
"baseUrl": "./src",
// Path mapping: sets 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 Recommendation:For new projects, the Node resolution strategy is recommended as it is currently the most commonly used approach.
Dynamic Import
Dynamic Import uses the import() syntax to load modules on demand at runtime.
This is very useful for code splitting and lazy loading.
Example
// import() returns a Promise
async function loadMath() {
// Dynamically import module; it is only loaded when execution reaches this point
var math = await import("./math");
// math.default is the default exported function
console.log("Dynamic Addition: " + math.default(1, 2));
}
// Call the lazy-loaded function
loadMath();
// Conditional import: dynamically load different modules based on conditions
async function loadFeature(enable: boolean) {
if (enable) {
// Only load the module when the condition is met
var feature = await import("./feature");
feature.run();
}
}
// Load based on condition
loadFeature(true);
Output:
动态加法: 3
Performance Optimization:Dynamic imports enable code splitting, loading additional code only when needed, reducing initial load time.
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:Enabling this option makes it easier to import CommonJS modules
Best Practices: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, performance optimization
- Module Resolution:Configure path aliases and resolution strategies
Other ExtensionsRecommendation:Organize module structure reasonably, use path aliases to simplify imports, and establish clear export/import conventions.