Migración gradual a null safety para proyectos grandes de Dart
La migración a null safety de Dart es un esfuerzo de 1-2 horas para un paquete pequeño y simple, pero puede ser un maratón de meses para un proyecto grande. Idealmente…
La migración a null safety de Dart es un esfuerzo de 1-2 horas para un paquete simple y pequeño, pero puede ser un maratón de varios meses para un proyecto grande. Idealmente, quieres migrar tu proyecto gradualmente — durante el maratón quieres mantener tu proyecto escalable, mantenible y fácil de publicar.
He migrado un proyecto grande a null safety y decidí reunir los pasos y consejos sobre cómo hacer el proceso confiable y eficiente, con la esperanza de que te ahorre tiempo.
Paso 1: Convertir a unsound null-safety
#Primero, migra tu proyecto a unsound null safety.
Comienza actualizando tus dependencias a versiones con null safety. Unsound null safety no requiere que todas las dependencias sean null-safe. Sin embargo, se recomienda encarecidamente esperar hasta que todas tus dependencias upstream estén migradas, ya que migrar una dependencia podría obligarte a revisitar decisiones de migración en tu propio código. Para paquetes que son mutuamente dependientes, podrías verte obligado a migrar fuera de orden o a migrar los paquetes concurrentemente (muchos paquetes mutuamente dependientes principalmente se referencian entre sí solo en las pruebas). Sigue la guía en dart.dev para actualizar tantas dependencias como puedas antes de migrar tu código.
A continuación, actualiza el SDK de Dart para tu paquete y marca cada biblioteca no migrada como legacy usando los siguientes pasos:
Asegúrate de que tu IDE (VSCode, IntelliJ / Android Studio) tenga el plugin de Dart instalado.
Abre tu paquete en el IDE y asegúrate de que no haya errores de compilación.
-
Actualiza la dependencia
dart_sdken el archivopubspec.yamlpara requerir el rango de versión:‘>=2.12.0 <3.0.0’. -
El IDE resaltará los errores relacionados con null safety en las bibliotecas que aún no son null-safe. Elimina los errores añadiendo el comentario
‘// @dart=2.9’al principio de cada archivo afectado. Añade el comentario a tu archivo main.dart incluso si no tiene errores, para mantener la app ejecutándose en modo unsound hasta que estés listo para cambiar. -
Verifica que todas las pruebas pasen y envía los cambios a tu rama principal. Si tus pruebas ya son null-safe, necesitarás el flag de línea de comando
--no-sound-null-safetypara suprimir los errores de null-safe.
Asegúrate de ver Running with unsound null-safety en la consola al iniciar la aplicación.
Ahora estás listo para migrar tu proyecto a sound null safety una biblioteca a la vez.
Paso 2: Iterar hacia sound null-safety
#Elige una biblioteca o un conjunto de bibliotecas para migrar.
Consejo pro: Si la biblioteca que seleccionaste es grande, puede que quieras dividirla en bibliotecas más pequeñas antes de migrar.
Usa dart pub deps para crear un grafo de dependencias de tu proyecto. Es mejor migrar los paquetes de abajo hacia arriba; comienza con las hojas en el árbol de dependencias y luego itera hacia la raíz. Sin embargo, si tu proyecto tiene ciclos de dependencias, esto puede no ser posible y está bien no seguir este orden.
Migra la biblioteca (o conjunto de bibliotecas) usando la herramienta de migración:
-
Inicia la herramienta interactiva de migración ejecutando
dart migrate --skip-import-check. Puede que quieras hacercdal directorio con las bibliotecas seleccionadas para facilitar la navegación en el árbol. -
Deselecciona todo deseleccionando las raíces del árbol de vista de archivos en el panel izquierdo. (Si te interesa, vota por un botón Deselect All.)
Usa
Control+Fpara encontrar el/los archivo(s) que quieres migrar.-
Selecciona el/los archivo(s) y haz clic en Apply Migration. Hay dos opciones para hacer ajustes: (1) usar comentarios para ajustar las elecciones de la herramienta antes de aplicar la migración o (2) usar un IDE para evaluar la nulabilidad de campos, parámetros y variables después de aplicar la migración.
-
Abre el paquete en el IDE. Corrige los errores y busca en los archivos los casos donde la herramienta puede ser inexacta (consulta una lista de posibles problemas a continuación). Haz correcciones y usa las advertencias de lint para limpiar interactivamente el código upstream y downstream.
No podrás corregir dos errores de lint:
import_of_legacy_library_into_null_safe(en bibliotecas migradas)avoid_redundant_argument_values(en bibliotecas legacy)
Por ahora, desactiva estos errores con comentarios. Los limpiarás más adelante, después de que la migración esté completa.
Posibles inexactitudes de la herramienta a vigilar:
-
Tipos añadidos
dynamiconum. Probablemente sabes qué tipo específico debería usarse en su lugar. En la mayoría de los casos,
bool?puede convertirse enboolcon un valor por defecto.-
Conversiones de tipo (busca
‘ as ‘) pueden significar que la herramienta no añadió un parámetro de tipo genérico. Después de añadirlo, un lint indica que la conversión se ha vuelto innecesaria y puede eliminarse. -
En algunos casos, la herramienta hace que el límite de un parámetro genérico sea nullable cuando podría ser mejor hacerlo non-nullable (busca
?>y?,). -
La herramienta podría hacer que cosas sean nullable que podrían expresarse mejor usando
lateolate final, o que podrían refactorizarse para permitir la inicialización en la lista de inicializadores del constructor. (Si te interesa, vota por un lint.) -
Usar una operación de aserción de null
!sin antes verificar un valor null puede significar que la variable o parámetro en realidad debería ser non-nullable. (Si te interesa, vota por un lint.) -
La herramienta añade conversiones para colecciones en la forma
collection as Iterable<TheType>. A veces, este cambio solo hace explícita una conversión que ya era implícita. Sin embargo, en otros casos, estas conversiones pueden introducir errores en tiempo de ejecución debido a discrepancias en la nulabilidad de los argumentos genéricos. Si tienes dudas, considera reemplazar la conversión con una conversión explícita por elemento (por ejemplo,collection.cast<TheType>()), o considera usar el método de extensiónwhereNotNulldepackage:collection. -
Si una variable, campo o parámetro es nullable, pero la nulabilidad se usa solo en las pruebas, quizás el código debería refactorizarse para eliminar la nulabilidad de ese identificador.
(Gracias a Kenzie Davisson, quien me ayudó a identificar estos casos.)
Paso 3: Limpieza
#Después de migrar todas tus bibliotecas, haz una limpieza final:
Limpia los comentarios que desactivan los lints.
Actualiza las dependencias restantes a versiones null-safe.
-
Asegúrate de que no queden comentarios de
//@dart = 2.9en tu app. En este punto, deberías verRunning with sound null-safetyen la consola al iniciar la app. Si no ves esto, o tienes bibliotecas que aún no están migradas (busca// @dart = 2.9), o una dependencia que no ha sido migrada. -
Asegúrate de que la app aún funcione correctamente y de que las pruebas pasen. Dado que el modo sound habilita garantías más fuertes en tiempo de ejecución, es posible (aunque poco probable) que veas nuevos errores en tiempo de ejecución que necesitas corregir al habilitar sound null safety. Normalmente esto es el resultado de convertir una colección nullable (como
List<int?>) a un tipo de colección non-nullable (comoList<int>).
¡Feliz migración!
Más de Dart
Dart en Google Summer of Code 2026
¡Estamos emocionados de anunciar que el proyecto Dart será mentor de contribuidores por séptima vez en Google Summer of Code 2026!
Resultados de Google Summer of Code 2025
El programa Google Summer of Code (GSoC) se enfoca en involucrar a nuevos desarrolladores de todo el mundo con el desarrollo de software de código abierto. Google…