Problemas de compatibilidad y optimización de CI que debes considerar antes de pasar a TypeScript 7
2026年7月29日
0
Computing/SoftwareComments (0)
Log in to leave a comment
No posts yet
Log in to leave a comment
No posts yet
Llegó TypeScript 7, reescrito desde cero en Go. Al enterarse de que la velocidad de verificación de tipos es hasta 12 veces más rápida, los equipos que manejan monorrepos a gran escala probablemente querrán migrar de inmediato. De hecho, los equipos de ingeniería de Vanta y VS Code revelaron que redujeron el tiempo de compilación en sus pipelines de CI en más del 80%.
Sin embargo, si lo aplicas a ciegas, todo tu CI fallará. Esto se debe a que, al cambiar a un binario nativo, el soporte para las API de análisis estático existentes se pospuso para versiones posteriores. Herramientas como @typescript-eslint o ts-morph, que inspeccionaban las API internas mediante require('typescript'), quedan completamente inhabilitadas. El rendimiento es atractivo, pero que la cadena de herramientas se rompa es un asunto distinto. Para evitar la interrupción de los despliegues y aprovechar las ventajas de velocidad, se necesitan algunas soluciones alternativas.
El binario tsc de TypeScript 7.0 bloquea por completo las llamadas a módulos internos de Node.js. Los paquetes que antes se importaban y usaban en un entorno JS generarán errores de inmediato al momento de la compilación. Si simplemente subes la versión sin preparación previa, todo el pipeline de CI se paralizará.
Es más seguro colocar un script de diagnóstico al inicio del pipeline. El enfoque consiste en recorrer todos los package.json y tsconfig.json dentro del workspace para identificar las opciones o paquetes que TypeScript 7 rechaza. Si quedan configuraciones de versiones antiguas como ignoreDeprecations o target: es5, el script arrojará un error de inmediato y detendrá el proceso.
`javascript
// scripts/check-ts7-compatibility.mjs
import fs from 'node:fs';
import { globSync } from 'glob';
const INCOMPATIBLE_DEPS = [
'ts-morph',
'ts-node',
'@babel/plugin-transform-typescript',
'typescript-eslint',
'@typescript-eslint/parser'
];
const DEPRECATED_TSCONFIG_OPTIONS = ['target:es5', 'moduleResolution:node', 'baseUrl', 'ignoreDeprecations'];
function runDiagnostics() {
console.log('TypeScript 7 호환성 사전 진단 시작...');
let hasError = false;
const packageFiles = globSync('/package.json', { ignore: '/node_modules/' });
for (const file of packageFiles) {
const content = JSON.parse(fs.readFileSync(file, 'utf8'));
const allDeps = { ...content.dependencies, ...content.devDependencies };
for (const dep of INCOMPATIBLE_DEPS) {
if (allDeps[dep]) {
console.warn([의존성 경고] ${file}: '${dep}' 패키지는 TS7 네이티브 API와 호환되지 않습니다.);
hasError = true;
}
}
}
const tsconfigFiles = globSync('/tsconfig*.json', { ignore: '/node_modules/' });
for (const file of tsconfigFiles) {
const rawContent = fs.readFileSync(file, 'utf8');
for (const opt of DEPRECATED_TSCONFIG_OPTIONS) {
if (rawContent.includes(opt)) {
console.error([설정 오류] ${file}: 무효화된 옵션 발견 -> '${opt}');
hasError = true;
}
}
}
if (hasError) process.exit(1);
}
runDiagnostics();
`
Los transformadores AST personalizados que dependen de ts.createProgram() o ts.transform() tampoco funcionarán. TypeScript 7.0 no acepta la inyección de plugins de JS externos. Esta lógica debe reemplazarse con módulos de bindings de Rust/C++ como SWC o Babel, o bien extraerse fuera de la etapa de compilación.
| Opción del compilador | Comportamiento en TypeScript 6.0 | Comportamiento en TypeScript 7.0 | Solución |
|---|---|---|---|
target |
Advertencia al usar es5 |
Hard Error (Interrumpe la compilación) | Cambiar a es2022 o superior |
moduleResolution |
Permite la configuración node |
Hard Error | Cambiar a bundler o node16 |
baseUrl |
Permite el uso individual | Hard Error | Migrar al uso exclusivo de compilerOptions.paths |
ignoreDeprecations |
Ignora las advertencias | Opción invalidada y error | Eliminar completamente esta configuración |
strict |
Valor por defecto false |
Valor por defecto true |
Establecer un valor explícito en tsconfig.json |
TypeScript 7 aprovecha el modelo de hilos de Go. Ofrece nuevas opciones como --checkers para procesar la verificación de tipos en paralelo y --builders para controlar la compilación de referencias de proyectos. El equipo de ingeniería de Slack combinó estas opciones para reducir el tiempo de verificación de tipos de 20 minutos a 4.5 minutos. Sin embargo, si asignas demasiados hilos sin considerar la cantidad de núcleos, la sobrecarga de cambio de contexto de la CPU aumentará y la compilación fallará por OOM (Out of Memory).
Es aconsejable ajustar los hilos según las especificaciones del runner utilizando la siguiente fórmula. Si llamamos a la cantidad de núcleos asignados a la máquina virtual, a la memoria total, a la memoria reservada para el sistema operativo () y al consumo promedio de memoria por worker (), el número óptimo de hilos para un solo proyecto se calcula de la siguiente manera:
N_{checkers} = minleft( C_{vCPU}, leftlfloor rac{M_{total} - M_{OS}}{M_{worker}} ight floor ight)La suma total de hilos, , no debe superar . Por ejemplo, en un entorno de runner con 8 vCPU / 16GB, una configuración de --checkers 4 y --builders 2 es adecuada.
`yaml
name: Monorepo Parallel Typecheck
on:
push:
branches: [main]
jobs:
typecheck:
runs-on: ubuntu-latest-8-core
steps:
- name: Checkout Codebase
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- name: Install Dependencies
run: pnpm install --frozen-lockfile
- name: Purge Legacy TS 6.0 Cache
run: find . -name "*.tsbuildinfo" -not -path "*/node_modules/*" -delete
- name: Execute TS 7 Parallel Check
run: npx tsc --build --checkers 4 --builders 2 --verbose
`
Hay un punto a tener en cuenta. El motor de compilación incremental de TS 7 no es compatible con el formato del archivo de caché .tsbuildinfo del antiguo TS 6. Si no eliminas la caché de la versión anterior con find . -name "*.tsbuildinfo" -delete antes de compilar, se producirá un error de segmentación (segmentation fault).
El servidor de lenguaje para editores también se renovó a un LSP basado en binarios de Go. Según los resultados de las pruebas de AWS CodeBuild, el tiempo que tarda en aparecer el primer error de tipo al abrir un archivo en un monorrepo grande se redujo de 17.5 segundos a 1.3 segundos.
Para unificar el entorno de VS Code de los miembros del equipo, basta con añadir la siguiente configuración en .vscode/settings.json en la raíz del monorrepo:
`json
{
"typescript.tsdk": "node_modules/typescript/lib",
"js/ts.experimental.useTsgo": true,
"typescript.enablePromptUseWorkspaceTsdk": true,
"typescript.preferences.preferTypeOnlyAutoImports": true,
"files.associations": {
"*.tsbuildinfo": "json"
}
}
`
A veces ocurren conflictos con plugins de lenguajes de plantilla como Vue o Svelte que hacen que el análisis sintáctico falle. En estos casos, puedes volver al motor tradicional de TS 6.0 presionando Ctrl+Shift+P para abrir la Paleta de comandos y seleccionando TypeScript: Select TypeScript Version... para continuar trabajando.
Si tu proyecto depende de paquetes antiguos y no puedes actualizar ESLint al entorno de TS 7 de inmediato, puedes resolverlo mediante una configuración de motor dual que utiliza ambos compiladores simultáneamente. Consiste en conectar la API de TS 6 a las herramientas de análisis estático y delegar únicamente la verificación de tipos real y la compilación al binario nativo de TS 7.
Define alias de paquetes en el package.json para instalar ambos compiladores al mismo tiempo:
`json
{
"name": "monorepo-root",
"private": true,
"devDependencies": {
"typescript": "npm:@typescript/typescript6@^6.0.2",
"@typescript/native": "npm:typescript@^7.0.2",
"eslint": "^9.0.0",
"typescript-eslint": "^8.0.0"
},
"scripts": {
"typecheck": "ts-native --build",
"typecheck:legacy": "tsc6 --noEmit",
"lint": "eslint ."
}
}
`
En este estado, es seguro adjuntar un script de compilación fantasma (Shadow Build) a tu CI. Al comparar los resultados de diagnóstico del TS 6 existente con los del TS 7 mediante diff, puedes monitorear si hay diferencias en los resultados de los tipos de plantilla literal o en la inferencia de tipos condicionales.
`bash
#!/usrbin/env bash
set -e
echo "=== 1. 기존 TS 6.0 컴파일러 진단 출력 생성 ==="
npx tsc6 --noEmit --pretty false > ./ts6-baseline.log 2>&1 || true
echo "=== 2. 신규 TS 7.0 네이티브 컴파일러 진단 출력 생성 ==="
npx --package @typescript/native tsc --noEmit --pretty false > ./ts7-output.log 2>&1 || true
echo "=== 3. 진단 결과 Diff 대조 검증 ==="
DIFF_RESULT=$(diff ./ts6-baseline.log ./ts7-output.log || true)
if [ -z "DIFF_RESULT"
exit 0
fi
`
Hasta que se resuelvan los problemas de compatibilidad en la cadena de herramientas, lo más práctico es operar separando los roles de linter y de verificador de tipos. Limpiando las opciones problemáticas con un script de diagnóstico previo y ajustando los hilos de acuerdo con las especificaciones de la infraestructura de CI, podrás obtener las mejoras de velocidad sin el inconveniente de que se detenga el pipeline de despliegue.