Inicio / Artículos

Actualizar una base de código React a TypeScript 6.0: ¿Qué se rompe primero?

Cómo afectan los valores predeterminados más estrictos de TypeScript 6.0, la corrección para la inferencia de métodos, las importaciones por subruta #/ y los tipos Temporal a una aplicación React, además de una lista de verificación segura para la actualización.

Editor: REACTAPP.TOP4 min de lectura842 palabras

Fuentes: TypeScript 6.0 for React Developers: What Actually Changed

La mayoría de las actualizaciones de los compiladores pasan desapercibidas. TypeScript 6.0 es diferente: es la última versión desarrollada sobre el compilador original de JavaScript y existe principalmente para preparar los repositorios de código para TypeScript 7, basado en Go; por lo tanto, trae menos características y más cambios que exponen problemas existentes. Esta guía explica cómo será realmente la experiencia al trabajar con un repositorio de código React y finaliza con una lista de verificación para la actualización. Para saber cómo encaja 6.0 en la transición hacia el compilador nativo, consulte el papel de puente de TypeScript 6 en el camino hacia un compilador nativo TS 7.

Primero vienen los valores predeterminados más estrictos

TypeScript 6.0 activa el modo estricto por defecto, asume módulos ES y cambia el objetivo predeterminado a es2025. Los proyectos que configuran cada opción de forma explícita no se ven afectados; aquellos que dependían de los antiguos valores predeterminados permisivos experimentarán una ola de nuevos errores. En el código de React, las víctimas habituales son los componentes antiguos: propiedades con tipado laxo, manejadores con parámetros implícitos de tipo any, referencias que pueden ser null, y useState() sin un argumento de tipo. Estos no son retrocesos, sino ambigüedades de larga data que ahora se reportan.

Los targets es3 y es5 también están obsoletos, por lo que el mínimo ahora es es2015. Para muchas aplicaciones React esto cambia poco, ya que Babel, SWC o esbuild se encargan de simplificar la sintaxis y tsc solo verifica los tipos, pero confírmelo antes de reconsiderar el soporte para navegadores. Ejecute la actualización en una rama separada con la compilación y las pruebas completas; cambiar los valores predeterminados del compilador un viernes por la tarde es una forma segura de arruinar un fin de semana.

Inferencia consistente para funciones de estilo método

Una solución menos problemática se refiere a los casos en que una función se considera “sensible al contexto”, lo que significa que sus tipos de parámetros deben provenir del contexto antes de que pueda continuar la inferencia. En 6.0, una expresión function o una abreviatura de método solo se trata de esta manera cuando realmente utiliza this. Antes, elegir la sintaxis de método en lugar de una función flecha podía cambiar la inferencia genérica incluso cuando this no se modificaba en absoluto. El ejemplo a continuación combina ambos estilos:

// Before: inconsistent inference depending on syntax
const useCounter = (initial) => {
  const [count, setCount] = useState(initial);

  // this pattern used to infer differently than an arrow fn
  const increment = function () {
    setCount((c) => c + 1);
  };

  return { count, increment };
};

Anteriormente, un callback como increment podía inferirse de manera diferente a una función flecha equivalente, y en hooks más complejos esa diferencia podía hacer que se transmitiera un tipo menos estricto a los llamantes. Ahora, la sintaxis que elijas para los callbacks y las funciones auxiliares devueltas ya no modifica los tipos resultantes, lo que elimina una fuente confusa de errores del tipo “¿por qué este callback no se verifica?”.

Importaciones más limpias con el prefijo #/

Las importaciones de subruta en Node definen alias privados en el campo imports de package.json, y TypeScript 6.0 admite el prefijo #/ allí, coincidiendo con los alias de raíz que suelen usar los bundlers. Declare la asignación una sola vez:

{
  "imports": {
    "#/*": "./src/*"
  }
}

Luego, los componentes importan desde la raíz del proyecto en lugar de contar los segmentos ../:

// No more relative path spaghetti in deeply nested components
import { useAuth } from "#/hooks/useAuth";
import { Button } from "#/components/ui/Button";

Dado que el alias se encuentra en package.json y no solo en tsconfig.json paths, Node y TypeScript lo resuelven de manera idéntica, sin necesidad de plugins adicionales. Solo se aplica en modos de resolución que leen las importaciones de package.json, como nodenext o bundler.

Los tipos temporales vienen integrados

TypeScript 6.0 incluye declaraciones para la API Temporal, que ha llegado a la fase final de estandarización en TC39. Los equipos que desarrollan interfaces de usuario para tareas de programación, reservas o paneles de control pueden utilizar Temporal.PlainDate o Temporal.ZonedDateTime sin necesidad de un paquete adicional, en lugar de lidiar con Date. Sin embargo, estos tipos no ofrecen soporte en tiempo de ejecución: verifique el soporte nativo en los navegadores y versiones de Node a los que se dirige, y agregue un polyfill cuando sea necesario.

¿Debería actualizar ahora?

Sí, de forma intencionada. El equipo de TypeScript presenta 6.0 como una actualización estable, pero los cambios subyacentes son reales:

  • Efectúe una auditoría de tsconfig.json y fije cada opción de la que dependa.
  • Corrija los nuevos errores del modo estricto en componentes antiguos en lugar de silenciarlos con any.
  • Confirme qué herramienta realiza la compatibilidad hacia versiones anteriores y qué versión de destino se requiere.
  • En bases de código con componentes de clase o almacenes gestionados por clases, considere habilitar noImplicitOverride para que los miembros sobrescritos requieran la palabra clave override.
  • Conclusión

    TypeScript 6.0 no cambiará la forma en que escribe código con React, pero pondrá de manifiesto los problemas ocultos por las configuraciones predeterminadas laxas. Resolverlos ahora, según su propio calendario, es mucho más económico que hacerlo más tarde en el año, al mismo tiempo que pasa de la versión 6 a la 7, lo cual convierte ese cambio posterior en algo principalmente relacionado con el rendimiento.