Descubre las novedades de TypeScript 5.8 Beta, incluyendo inferencia de tipos de retorno más inteligente, mejor soporte para módulos de Node.js y optimizaciones de rendimiento.
TypeScript 5.8 Beta ya está aquí, trayendo mejoras emocionantes para los desarrolladores que trabajan con inferencia de tipos avanzada, interoperabilidad de módulos de Node.js y optimizaciones de rendimiento. Esta actualización introduce retornos verificados para tipos de acceso indexado y condicional, soporte mejorado para require() en Módulos de ECMAScript (ESM), y nuevas banderas del compilador que mejoran la experiencia del desarrollador.
Sumerjámonos en las funcionalidades clave de TypeScript 5.8 y cómo pueden mejorar tu flujo de trabajo de desarrollo.
Retornos verificados para tipos de acceso indexado y condicional
Una de las funcionalidades destacadas en TypeScript 5.8 es una mejor verificación para los tipos de retorno cuando se usan tipos condicionales. Anteriormente, al definir una función que retornaba un tipo condicional, los desarrolladores tenían que usar aserciones de tipo para satisfacer el sistema de tipos de TypeScript. Ahora, TypeScript puede inferir el tipo de retorno correcto automáticamente, mejorando tanto la seguridad de tipos como la ergonomía para el desarrollador.
El problema: Tipos de retorno poco claros
Considera una función showQuickPick que permite a un usuario seleccionar una o varias opciones de una lista:
async function showQuickPick(
prompt: string,
selectionKind: SelectionKind,
items: readonly string[]
): Promise<string | string[]> {
// Implementación...
}
Aquí, el tipo de retorno es Promise<string | string[]>, lo que significa que quienes llaman a la función deben verificar manualmente el tipo antes de usarlo. Esto puede llevar a errores, como se ve en el siguiente ejemplo:
let shoppingList = await showQuickPick(
'¿Qué frutas quieres comprar?',
SelectionKind.Multiple,
['manzanas', 'naranjas', 'bananos', 'durian']
);
console.log(`Saliendo a comprar ${shoppingList.join(', ')}`);
// ⚠️ Error: La propiedad 'join' no existe en el tipo 'string | string[]'.
Dado que shoppingList podría ser un string o un string[], TypeScript no sabe cuál es en tiempo de compilación.
La solución: Tipos de retorno condicionales
Con TypeScript 5.8, puedes definir tipos de retorno precisos usando un tipo condicional:
type QuickPickReturn<S extends SelectionKind> = S extends SelectionKind.Multiple
? string[]
: string;
async function showQuickPick<S extends SelectionKind>(
prompt: string,
selectionKind: S,
items: readonly string[]
): Promise<QuickPickReturn<S>> {
// Implementación...
}
Ahora, TypeScript infiere correctamente el tipo de retorno esperado:
let shoppingList: string[] = await showQuickPick(
'¿Qué frutas quieres comprar?',
SelectionKind.Multiple,
['manzanas', 'naranjas', 'bananos', 'durian']
); // ✅ Inferido correctamente como `string[]`
let dinner: string = await showQuickPick(
"¿Qué hay de cena?",
SelectionKind.Single,
['sushi', 'pasta', 'tacos']
); // ✅ Inferido correctamente como `string`
Mejora en la verificación de tipos en las implementaciones
Anteriormente, implementar una función con tipos de retorno condicionales de orden superior requería aserciones de tipo explícitas, lo que podía llevar a bugs en tiempo de ejecución. TypeScript 5.8 elimina este requisito al habilitar el análisis de flujo de control para tipos condicionales genéricos.
if (selectionKind === SelectionKind.Single) {
return selectedItems[0]; // ✅ ¡No se necesita aserción de tipo!
} else {
return selectedItems;
}
Este cambio mejora la seguridad de tipos y evita que los desarrolladores intercambien por error los valores de retorno en diferentes ramas.
Soporte para require() de Módulos ECMAScript en --module nodenext
Un punto de dolor de larga data en el desarrollo con Node.js ha sido la dificultad de la interoperabilidad entre CommonJS y Módulos ECMAScript (ESM). En Node.js:
- Los archivos ESM pueden importar (
import) archivos CommonJS ✅ - Los archivos CommonJS no pueden requerir (
require()) archivos ESM ❌
Esto ha obligado a los desarrolladores a realizar una doble publicación de bibliotecas (proporcionando versiones ESM y CommonJS) o a quedarse en CommonJS indefinidamente.
Con Node.js 22, esta restricción se relaja: los archivos CommonJS ahora pueden requerir (require()) archivos ESM, siempre que el archivo ESM no utilice await en el nivel superior (top-level await). TypeScript 5.8 ahora soporta este comportamiento cuando se usa --module nodenext.
Lo que esto significa para los desarrolladores
Si estás desarrollando un paquete de Node.js, ya no necesitas la doble publicación para la compatibilidad con CommonJS y ESM. En su lugar, puedes simplemente habilitar --module nodenext, y TypeScript dejará de emitir errores en las llamadas a require("esm").
const esmModule = require('./algun-modulo-esm.js'); // ✅ Ahora es válido en TypeScript 5.8
Por ahora, los autores de bibliotecas que apuntan a versiones anteriores de Node.js deben mantenerse en --module node16 o --module node18, mientras que los usuarios en Node.js 22+ deberían usar --module nodenext.
Nuevas banderas del compilador para una mejor experiencia de desarrollo
--erasableSyntaxOnly: Código TypeScript más estricto para la compatibilidad con Node.js
Dado que Node.js 23.6 añade soporte experimental para ejecutar archivos TypeScript directamente, se impone una regla clave: la sintaxis de TypeScript debe ser completamente eliminable (erasable), lo que significa que no se permiten enums, espacios de nombres (namespaces) ni alias de importación.
TypeScript 5.8 introduce la bandera --erasableSyntaxOnly para imponer esta restricción en tiempo de compilación.
class MyClass {
constructor(public x: number) {}
// ❌ Error: Las propiedades de parámetros no están permitidas bajo `--erasableSyntaxOnly`
}
Esta bandera ayuda a los desarrolladores a escribir TypeScript que sea directamente ejecutable en Node.js sin un paso de compilación separado.
Optimizaciones de rendimiento en TypeScript 5.8
TypeScript 5.8 introduce varias optimizaciones que mejoran los tiempos de construcción y la capacidad de respuesta del editor:
- Normalización de rutas más rápida
- TypeScript evita asignaciones de arreglos innecesarias al resolver rutas, acelerando las construcciones de proyectos grandes.
- Compilación incremental más inteligente
- En el modo
--watch, TypeScript evita volver a validar opciones del compilador que no han cambiado, haciendo que las reconstrucciones sean más rápidas después de las ediciones.
- En el modo
Para bases de código grandes, estos cambios deberían resultar en mejoras notables de velocidad al trabajar en editores o ejecutar construcciones de TypeScript.
Otros cambios notables en TypeScript 5.8
- Bandera
--module node18:- Proporciona una alternativa estable a
nodenextpara usuarios en Node.js 18.
- Proporciona una alternativa estable a
- Bandera
--libReplacement:- Permite desactivar las búsquedas automáticas de paquetes
lib, mejorando el rendimiento en proyectos que no usan tipados de DOM personalizados.
- Permite desactivar las búsquedas automáticas de paquetes
- Nombres de propiedades computadas preservados en archivos de declaración:
- TypeScript ahora mantiene los nombres de propiedades computadas en los archivos de declaración, mejorando la predictibilidad de tipos para las bibliotecas.
Conclusión
TypeScript 5.8 introduce varias mejoras amigables para el desarrollador, desde una inferencia de tipos de retorno más inteligente hasta una mejor interoperabilidad ESM/CommonJS y construcciones más rápidas. Estas actualizaciones ayudan a optimizar la seguridad de tipos, el rendimiento y el soporte moderno de Node.js.
Para probar TypeScript 5.8 Beta hoy mismo, ejecuta:
npm install -D typescript@beta
Para más detalles, consulta la publicación oficial en el blog de Microsoft.