Sistema de módulos de TypeScript
El sistema de módulos es la base del desarrollo moderno de TypeScript.
TypeScript es totalmente compatible con la sintaxis de ES Module y ofrece una amplia variedad de estrategias de resolución de módulos.
Mediante el sistema de módulos, se puede dividir el código en unidades reutilizables, logrando organización y reutilización del código.
Diagrama SVG: exportación e importación de módulos
¿Por qué se necesita un sistema de módulos?
A medida que crece el tamaño del proyecto, la cantidad de código aumenta cada vez más.
Al distribuir el código en múltiples archivos y organizarlo mediante módulos, se puede mejorar la mantenibilidad y la reutilización del código.
El sistema de módulos hace que cada archivo tenga su propio ámbito, evitando la contaminación de variables globales.
Explicación del concepto:Un módulo es un archivo de TypeScript que contiene sentencias de exportación e importación. El contenido se exporta mediante `export` y se importa mediante `import`.
Exportación de módulos
Con la palabra clave `export` se pueden exportar variables, funciones, clases, interfaces, etc., para que otros módulos las utilicen.
Módulo user.ts
export var name = "Alice";
export const age = 25;
// Exportar función
export function greet(message: string): string {
return "Hello, " + message;
}
// Exportar clase
export class User {
// Propiedades de parámetros del constructor
constructor(public name: string) {}
// Método de presentación
introduce(): string {
return "I am " + this.name;
}
}
// Exportar interfaz (la interfaz desaparece tras la compilación, solo se usa para la verificación de tipos)
export interface Config {
// Configurar host
host: string;
// Configurar puerto
port: number;
}
// Exportación por lotes: exportación con renombrado
export { name as userName, age as userAge };
Nota:Las interfaces y los tipos no generan código real en el JavaScript compilado; solo se utilizan para la verificación de tipos de TypeScript.
Importación de módulos
Usa la palabra clave `import` para importar el contenido exportado desde otros módulos.
main.ts importa el módulo
import { name, age, greet } from "./user";
// Importación por defecto: importa la exportación por defecto del módulo
import User from "./user";
// Importación total: coloca todas las exportaciones del módulo en un objeto
import * as UserModule from "./user";
// Importación con renombrado: evita conflictos de nombres
import { greet as sayHello } from "./user";
// Usar el contenido importado
console.log(greet("World"));
console.log(sayHello("TypeScript"));
Resultado de ejecución:
Hello, World Hello, TypeScript
Explicación de rutas:La ruta de importación puede ser una ruta relativa (como
./user) o una ruta absoluta (como@/utils)。
Exportación por defecto
Cada módulo puede tener una exportación por defecto.
La exportación por defecto no requiere llaves al importarse y se le puede asignar cualquier nombre.
Módulo math.ts
export default function add(a: number, b: number): number {
return a + b;
}
// Se puede combinar con otras exportaciones
export function multiply(a: number, b: number): number {
return a * b;
}
Importación en main.ts
import add from "./math";
// Importar exportaciones con nombre: se requieren llaves
import { multiply } from "./math";
console.log("Suma: " + add(2, 3));
console.log("Multiplicación: " + multiply(4, 5));
Resultado de ejecución:
加法: 5 乘法: 20
Sugerencia:Para el contenido principal de exportación, como funciones de utilidad y clases, usa la exportación por defecto; para funciones auxiliares, interfaces, etc., usa exportaciones con nombre.
Re-exportación
La re-exportación (Re-export) se utiliza para agregar el contenido de múltiples módulos, o para exponer las exportaciones de un módulo a otro.
Módulo agregador index.ts
export { name, age } from "./user";
// Re-exportar la exportación por defecto (requiere renombrar)
export { default as User } from "./user";
// Re-exportar todo el contenido
export * from "./math";
Casos de uso:Usa index.ts como archivo de entrada para exportar de forma centralizada el contenido de los submódulos, facilitando la importación unificada.
Estrategia de resolución de módulos
TypeScript ofrece múltiples estrategias de resolución de módulos para localizar los módulos importados.
Se puede configurar en tsconfig.json.
Configuración de tsconfig.json
"compilerOptions": {
// Estrategia de resolución de Node
// Sigue las reglas de resolución de módulos de Node.js
"moduleResolution": "node",
// Estrategia de resolución clásica
// Estrategia utilizada en versiones tempranas de TypeScript
"moduleResolution": "classic",
// baseUrl: establece la ruta base
// Todas las importaciones de rutas no relativas se resuelven a partir de esta ruta
"baseUrl": "./src",
// Mapeo de rutas: establece alias para las rutas de importación
"paths": {
// Las importaciones que comienzan con @ se mapean al directorio src
"@/*": ["./*"],
// Las importaciones que comienzan con @components se mapean al directorio components
"@components/*": ["./components/*"]
}
}
}
Sugerencia de configuración:Para proyectos nuevos se recomienda usar la estrategia de resolución de Node, que es actualmente la más utilizada.
Importación dinámica
La importación dinámica (Dynamic Import) utiliza la sintaxis `import()` y permite cargar módulos bajo demanda en tiempo de ejecución.
Esto es muy útil para la división de código y la carga diferida (lazy loading).
Ejemplo
// import() devuelve una Promise
async function loadMath() {
// Importación dinámica del módulo: solo se carga al ejecutar esta línea
var math = await import("./math");
// math.default es la función exportada por defecto
console.log("Suma dinámica: " + math.default(1, 2));
}
// Llamar a la función de carga diferida
loadMath();
// Importación condicional: carga dinámicamente diferentes módulos según la condición
async function loadFeature(enable: boolean) {
if (enable) {
// Solo se carga el módulo cuando se cumple la condición
var feature = await import("./feature");
feature.run();
}
}
// Cargar según la condición
loadFeature(true);
Resultado de ejecución:
动态加法: 3
Optimización del rendimiento:La importación dinámica permite la división de código, cargando código adicional solo cuando se necesita, lo que reduce el tiempo de carga inicial.
Consideraciones
- Rutas relativas:Usa rutas relativas para importar módulos locales (./, ../)
- Extensión de módulos:TypeScript maneja automáticamente las extensiones durante la compilación
- Por defecto vs. con nombre:Cada módulo tiene una exportación por defecto y múltiples exportaciones con nombre
- esModuleInterop:Habilitar esta opción facilita la importación de módulos CommonJS
Mejores prácticas:Mantén las rutas de importación coherentes, usa alias de ruta para simplificar rutas largas y establece una estructura de organización de módulos clara.
Resumen
El sistema de módulos es el núcleo de la organización de proyectos TypeScript.
- export:Exportar variables, funciones, clases e interfaces
- import:Importar el contenido exportado
- Exportación por defecto:Una por módulo, de uso flexible
- Re-exportación:Agregar módulos, crear archivos de entrada
- Importación dinámica:Carga diferida, optimizar el rendimiento
- Resolución de módulos:Configurar alias de ruta y estrategias de resolución
Otras extensionesSugerencia:Organiza razonablemente la estructura de módulos, usa alias de ruta para simplificar las importaciones y establece normas claras de exportación e importación.