En el desarrollo enterprise moderno y en monorrepositorios a gran escala (Turborepo, Nx, Lerna), la transpilación de código JavaScript hace tiempo que dejó de ser el cuello de botella principal. Las herramientas nativas de nueva generación escritas en Rust y Go (SWC, esbuild, Oxc, Rolldown) transforman millones de líneas de código decenas de veces más rápido que el compilador monohilo clásico tsc.
Sin embargo, durante la publicación de librerías y paquetes persistía un cuello de botella crítico: la generación de archivos de declaraciones de tipos (.d.ts).
Históricamente, los transpiladores rápidos archivo por archivo (Single-File Transpilers) no podían emitir archivos .d.ts. La razón radica en que si una función o constante exportada carece de anotación explícita de tipos, el compilador está obligado a inspeccionar las implementaciones de todas las dependencias upstream:
// Para generar el .d.ts de este archivo:
import { getUser } from './user-service';
export const currentUser = getUser(); // ¿Cuál es el tipo de currentUser?Para calcular el tipo de currentUser, tsc debe construir un grafo semántico global de tipos de todo el proyecto, navegar a user-service.ts y analizar su cuerpo y cadena de importaciones. Los transpiladores de un solo archivo en Rust/Go no inspeccionan archivos vecinos en el sistema de archivos ni ejecutan análisis semántico global. Debido a esto, la fase de compilación de tipos en CI/CD se estancaba inexorablemente en el lento tsc --declaration.
La solución a este problema fundamental en TypeScript 5.5+ es el flag del compilador --isolatedDeclarations.
El flag --isolatedDeclarations exige tipado explícito en la frontera pública de los módulos: cada archivo puede generar su .d.ts de forma completamente autónoma. Esto desbloquea la generación de tipos mediante compiladores multihilo nativos (Oxc, SWC, Rolldown) logrando aceleraciones de 30x a 50x en CI/CD.
El concepto isolatedDeclarations establece una separación estricta de áreas de responsabilidad arquitectónica:
Si el compilador detecta export function calculate(a: number, b: number) { return a + b; }, el modo --isolatedDeclarations emitirá el error TS9007: «Exported function must have an explicit return type».
Gracias a esta regla, un generador nativo (como Oxc en Rust) ya no necesita parsear los cuerpos de las funciones: lee únicamente las firmas de cabecera (export function calculate(a: number, b: number): number) y descarga de inmediato el archivo .d.ts a disco.
+-------------------------------------------------------------------------+
| Evolución de la generación de archivos de declaración (.d.ts)|
+-------------------------------------------------------------------------+
| Pipeline tradicional (tsc --declaration): |
| [Archivo A] ──┐ |
| [Archivo B] ──┼──> [tsc Global Type Checker] ──> [Archivos .d.ts] |
| [Archivo C] ──┘ • Monohilo, lento (runtime Node.js) |
| • Requiere construir el grafo de tipos de TODAS las |
| dependencias |
+-------------------------------------------------------------------------+
│
▼ Flag --isolatedDeclarations (TS 5.5+)
+-------------------------------------------------------------------------+
| Pipeline nativo paralelo (Oxc / Rolldown / SWC): |
| [Archivo A (Tipos explícitos)] ──> [Hilo Rust 1] ──> [Archivo A.d.ts] |
| [Archivo B (Tipos explícitos)] ──> [Hilo Rust 2] ──> [Archivo B.d.ts] |
| [Archivo C (Tipos explícitos)] ──> [Hilo Rust 3] ──> [Archivo C.d.ts] |
| • Emisión independiente archivo por archivo (Single-file emit) |
| • Aceleración de emisión de tipos de 30x a 50x en procesadores |
| multinúcleo |
+-------------------------------------------------------------------------+Agregar los parámetros 'isolatedDeclarations': true y 'declaration': true a la sección compilerOptions.
Ejecutar tsc --noEmit y agregar anotaciones explícitas de tipos de retorno en funciones y constantes exportadas.
Garantizar que todas las interfaces y DTOs utilizados en firmas públicas lleven la palabra clave export.
Reemplazar la invocación de tsc --declaration por la emisión paralela de .d.ts mediante Oxc o Rolldown para builds casi instantáneos.
¿Por qué activar isolatedDeclarations prohíbe exportar 'export const config = { retries: 3, timeout: 5000 };' sin tipo explícito o as const?
En monorrepositorios empresariales con cientos de paquetes, la generación de tipos con tsc solía tardar entre 10 y 15 minutos. Migrar paquetes a --isolatedDeclarations y emitir tipos en paralelo con Rust (Oxc/Rolldown) reduce esta fase a 10–20 segundos.
La obligación de tipar explícitamente las funciones exportadas protege a las librerías frente a breaking changes accidentales: un desarrollador no puede alterar involuntariamente el tipo de retorno público al modificar bifurcaciones internas if/else.
Integración de Rolldown (empaquetador nativo en Rust) para generar simultáneamente el bundle JavaScript y el árbol de declaraciones .d.ts en un solo paso ultrarrápido sin sobrecarga del runtime de Node.js.
Herramientas como oxlint detectan automáticamente la falta de anotaciones en exportaciones y aplican autofixes insertando los tipos computados directamente en el código fuente.
Veamos las reglas de diseño de código compatibles con el estándar isolatedDeclarations y la configuración del proyecto.
Habilitar 'isolatedDeclarations': true y 'declaration': true en tsconfig.json.
tsc u oxlint comprueba la existencia de tipos explícitos en todas las sentencias export públicas.
El parser nativo de Oxc lee únicamente las firmas de cabecera, descartando la implementación al instante.
Los hilos del sistema operativo descargan sincrónicamente archivos .d.ts a disco con consumo mínimo de memoria.
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"declaration": true,
// Habilitar el modo estricto de declaraciones aisladas (TS 5.5+)
"isolatedDeclarations": true,
// Recomendado junto con isolatedModules
"isolatedModules": true,
"strict": true,
"skipLibCheck": true
}
}export interface UserProfile {
readonly id: string;
readonly name: string;
readonly roles: readonly string[];
}
// ─────────────────────────────────────────────────────────────
// 1. Exportación de funciones: Tipo de retorno explícito OBLIGATORIO
// ─────────────────────────────────────────────────────────────
// ❌ ERROR TS9007 bajo isolatedDeclarations:
// export function fetchUser(id: string) {
// return { id, name: 'Alice', roles: ['admin'] };
// }
// ✅ CORRECTO: La firma fija explícitamente el contrato
export function fetchUser(id: string): UserProfile {
return {
id,
name: 'Alice',
roles: ['admin'],
};
}
// ─────────────────────────────────────────────────────────────
// 2. Exportación de constantes: Tipo explícito o as const OBLIGATORIO
// ─────────────────────────────────────────────────────────────
export interface ClientConfig {
readonly timeoutMs: number;
readonly retryCount: number;
}
// ✅ Opción A: Tipo de interfaz explícito
export const DEFAULT_CONFIG: ClientConfig = {
timeoutMs: 5000,
retryCount: 3,
};
// ✅ Opción B: Aserción constante con as const
export const HTTP_STATUS = {
OK: 200,
NOT_FOUND: 404,
INTERNAL_ERROR: 500,
} as const;
// ─────────────────────────────────────────────────────────────
// 3. Clases: Miembros públicos requieren tipos explícitos
// ─────────────────────────────────────────────────────────────
export class ApiGateway {
// Las propiedades públicas requieren tipo explícito
public readonly endpoint: string;
constructor(endpoint: string) {
this.endpoint = endpoint;
}
// Los métodos públicos requieren tipo de retorno explícito
public getUrl(path: string): string {
return `${this.endpoint}${path}`;
}
// ¡Los métodos privados NO requieren anotaciones porque se omiten en el .d.ts!
private calculateBackoff(attempt: number) {
return Math.pow(2, attempt) * 100;
}
}Una función se declara como: 'interface InternalData { hash: string; } export function getHash(): InternalData { ... }'. ¿Por qué tsc con isolatedDeclarations arroja el error TS9010?
Ejemplo de configuración de un paquete en monorrepositorio con integración del compilador nativo Oxc para emisión instantánea de declaraciones .d.ts combinado con verificación desacoplada mediante tsc --noEmit.
{
"name": "@agenticlab/core-engine",
"version": "1.0.0",
"type": "module",
"scripts": {
"typecheck": "tsc --noEmit",
"build:code": "rolldown -c rolldown.config.ts",
"build:types": "oxc-transform --emit-declarations src -d dist/types",
"build": "pnpm run typecheck && pnpm run build:code && pnpm run build:types"
},
"devDependencies": {
"oxc-transform": "^0.15.0",
"rolldown": "^0.14.0",
"typescript": "^5.5.0"
}
}Si una función exportada retorna una interfaz local sin la palabra clave export, un generador de archivo único no podrá producir un archivo de declaración válido porque los consumidores externos no podrán resolver el nombre del tipo.
// ❌ ERROR: ¡La interfaz local no está exportada!
interface SecretConfig { key: string; }
export function loadConfig(): SecretConfig { /* ... */ }
// Error TS9010: Variable must have an explicit type, but its type cannot be named.
// ✅ CORRECTO: Exportar la interfaz junto con la función
export interface SecretConfig { key: string; }
export function loadConfig(): SecretConfig { /* ... */ }Los emisores como Oxc y SWC realizan exclusivamente emisión sintáctica de .d.ts a partir de anotaciones explícitas existentes. No realizan comprobación semántica de tipos (Type Checking). Eliminar tsc --noEmit de los pasos de CI/CD permite que errores lógicos graves de tipos se cuelen a producción.
El flag --isolatedDeclarations se aplica estrictamente a la superficie pública del módulo (export). Intentar anotar cada variable interna dentro de funciones o métodos privados de clase (private helper(): void) añade ruido visual innecesario sin aportar beneficios al compilador.
El flag --isolatedDeclarations en TypeScript 5.5+ revoluciona el rendimiento de compilación en bases de código a gran escala. Al imponer la disciplina de tipado explícito en la frontera de exportaciones públicas, desvincula la generación de declaraciones .d.ts del proceso monohilo de tsc y la transfiere a compiladores ultrarrápidos de última generación en Rust (Oxc, Rolldown, SWC), acelerando los pipelines de CI/CD de monorrepositorios decenas de veces.