Migração gradual para o null safety em projetos Dart grandes
A migração para o null safety do Dart é um trabalho de 1 a 2 horas para um pacote simples e pequeno, mas pode virar uma maratona de meses em um projeto grande. Idealmente…
A migração para o null safety do Dart é um trabalho de 1 a 2 horas para um pacote simples e pequeno, mas pode virar uma maratona de meses em um projeto grande. Idealmente, você quer migrar o projeto de forma gradual — durante a maratona, é importante manter o projeto crescendo, fácil de manter e fácil de lançar.
Eu migrei um projeto grande para o null safety e decidi reunir passos e dicas para tornar o processo confiável e eficiente, na esperança de economizar seu tempo.
Passo 1: migrar para o null safety unsound
#Primeiro, migre seu projeto para o null safety unsound.
Comece atualizando suas dependências para versões com null safety. O null safety unsound não exige que todas as dependências sejam null-safe. No entanto, é altamente recomendável esperar até que todas as suas dependências upstream estejam migradas, pois migrar uma dependência pode obrigar você a revisar decisões de migração no seu próprio código. Para pacotes que dependem mutuamente uns dos outros, você pode ser forçado a migrar fora de ordem ou a migrar os pacotes ao mesmo tempo (muitos pacotes que dependem mutuamente se referem uns aos outros apenas nos testes). Siga as orientações do dart.dev para atualizar o máximo de dependências que puder antes de migrar o seu código.
Em seguida, atualize o SDK do Dart para o seu pacote e marque cada biblioteca não migrada como legacy, seguindo estes passos:
-
Certifique-se de que sua IDE (VSCode, IntelliJ / Android Studio) tem o plugin do Dart instalado.
Abra seu pacote na IDE e certifique-se de que não há erros de compilação.
-
Atualize a dependência
dart_sdkno arquivopubspec.yamlpara exigir a faixa de versão:‘>=2.12.0 <3.0.0’. -
A IDE vai destacar os erros relacionados ao null safety em bibliotecas que ainda não são null-safe. Remova os erros adicionando o comentário
‘// @dart=2.9’no topo de cada arquivo afetado. Adicione o comentário ao seu arquivo main.dart mesmo que ele não tenha erros, para manter o app rodando no modo unsound até que você esteja pronto para trocar. -
Verifique se todos os testes passam e envie as mudanças para sua branch principal. Se os seus testes já forem null-safe, você vai precisar da flag de linha de comando
--no-sound-null-safetypara suprimir os erros de null safety.
Certifique-se de ver Running with unsound null-safety no console ao iniciar a aplicação.
Agora você está pronto para migrar seu projeto para o sound null safety, uma biblioteca por vez.
Passo 2: avançar em direção ao sound null safety
#Escolha uma biblioteca ou um conjunto de bibliotecas para migrar.
Dica de ouro: se a biblioteca escolhida for grande, talvez seja bom dividi-la em bibliotecas menores antes de migrar.
Use dart pub deps para criar um grafo de dependências do seu projeto. O ideal é migrar os pacotes de baixo para cima: comece pelas folhas da árvore de dependências e vá subindo até a raiz. No entanto, se o seu projeto tiver ciclos de dependência, isso pode não ser possível, e tudo bem não seguir essa ordem.
Migre a biblioteca (ou o conjunto de bibliotecas) usando a ferramenta de migração:
-
Inicie a ferramenta de migração interativa executando
dart migrate --skip-import-check. Você pode querer usarcdpara ir até o diretório com as bibliotecas selecionadas, para facilitar a navegação na árvore. -
Desmarque tudo, desmarcando as raízes da árvore de arquivos no painel da esquerda. (Se tiver interesse, vote por um botão Deselect All.)
Use
Control+Fpara encontrar o(s) arquivo(s) que você quer migrar.-
Selecione o(s) arquivo(s) e clique em Apply Migration. Há duas opções para fazer ajustes: (1) usar comentários para ajustar as escolhas da ferramenta antes de aplicar a migração ou (2) usar a IDE para avaliar a nulabilidade de campos, parâmetros e variáveis depois de aplicar a migração.
-
Abra o pacote na IDE. Corrija os erros e pesquise nos arquivos os casos em que a ferramenta pode ter errado (veja a lista de possíveis problemas abaixo). Faça as correções e use os avisos de lint para limpar interativamente o código upstream e downstream.
Você não vai conseguir corrigir dois erros de lint:
import_of_legacy_library_into_null_safe(em bibliotecas migradas)avoid_redundant_argument_values(em bibliotecas legacy)
Por enquanto, desative esses erros com comentários. Você vai limpar isso depois, quando a migração estiver concluída.
Imprecisões da ferramenta a observar:
-
Tipos adicionados como
dynamicounum. Quase sempre você sabe qual tipo específico deveria ser usado no lugar. Na maioria dos casos,
bool?pode virarboolcom um valor padrão.-
Casts de tipo (pesquise por
‘ as ‘) podem significar que a ferramenta não adicionou um parâmetro de tipo genérico. Depois de adicioná-lo, um lint indica que o cast se tornou desnecessário e pode ser removido. -
Em alguns casos, a ferramenta torna nulável o limite de um parâmetro genérico, quando talvez fosse melhor torná-lo não nulável (pesquise por
?>e?,). -
A ferramenta pode tornar nullable coisas que seriam melhor expressas com
lateoulate final, ou que poderiam ser refatoradas para permitir a inicialização na lista de inicializadores do construtor. (Se tiver interesse, vote por um lint.) -
Usar um operador de asserção nula
!sem antes verificar se o valor é nulo pode significar que a variável ou o parâmetro deveria ser, na verdade, não nulável. (Se tiver interesse, vote por um lint.) -
A ferramenta adiciona casts para coleções na forma
collection as Iterable<TheType>. Às vezes, essa mudança apenas torna explícito um cast que já era implícito. Em outros casos, esses casts podem introduzir erros de tempo de execução por causa de incompatibilidades de nulabilidade dos argumentos genéricos. Na dúvida, considere substituir o cast por uma conversão explícita elemento por elemento (por exemplo,collection.cast<TheType>()), ou considere usar o método de extensãowhereNotNulldopackage:collection. -
Se uma variável, campo ou parâmetro é nulável, mas a nulabilidade só é usada nos testes, talvez o código deva ser refatorado para remover a nulabilidade desse identificador.
(Agradecimentos a Kenzie Davisson, que me ajudou a identificar esses casos.)
Passo 3: limpeza
#Depois de migrar todas as suas bibliotecas, faça uma limpeza final:
Limpe os comentários de desativação dos lints.
Atualize as dependências restantes para versões com null safety.
-
Garanta que não restem comentários
//@dart = 2.9no seu app. Neste ponto, você deve verRunning with sound null-safetyno console ao iniciar o app. Se não vir isso, você tem bibliotecas que ainda não foram migradas (pesquise por// @dart = 2.9) ou uma dependência que ainda não foi migrada. -
Garanta que o app continua funcionando corretamente e que os testes passam. Como o modo sound oferece garantias de tempo de execução mais fortes, é possível (embora improvável) que você veja novos erros de tempo de execução que precisará corrigir ao ativar o sound null safety. Normalmente, isso é resultado de fazer cast de uma coleção nullable (como
List<int?>) para um tipo de coleção não nulável (comoList<int>).
Boa migração!
Mais do Dart
Resultados do Google Summer of Code 2026
Hoje, destacamos os projetos e os resultados dos colaboradores orientados pelo Dart e pelo Flutter no Google Summer of Code 2026.
Dart no Google Summer of Code 2026
Estamos animados para anunciar que o projeto Dart será mentor de contribuidores pela sétima vez no Google Summer of Code 2026!