Skip to content

Instantly share code, notes, and snippets.

@evaisse
Created September 12, 2025 09:58
Show Gist options
  • Select an option

  • Save evaisse/405eec5048c1eac9bf682309753902b2 to your computer and use it in GitHub Desktop.

Select an option

Save evaisse/405eec5048c1eac9bf682309753902b2 to your computer and use it in GitHub Desktop.
dart 3.6/3.7/3.8

Nouveautés de Dart pour les version 3.6, 3.7 et 3.8

Ce document présente toutes les fonctionnalités et améliorations majeures apparues dans Dart entre les versions 3.5 (août 2024) et 3.8 (mai 2025).

Dart 3.6 (Novembre 2024)

1. Séparateurs de chiffres (Digit Separators)

La fonctionnalité principale de Dart 3.6 est l'introduction des séparateurs de chiffres pour améliorer la lisibilité des nombres.

// Configuration requise dans pubspec.yaml
// sdk: '>=3.6.0'

// Exemples d'utilisation des séparateurs de chiffres
void main() {
  // Nombres décimaux
  const population = 8_000_000_000; // 8 milliards
  const budget = 1_234_567_890.50;
  
  // Notation hexadécimale
  const memoryAddress = 0x00FF_00FF_00FF;
  const macAddress = 0x00_14_22_01_23_45;
  
  // Notation scientifique
  const avogadro = 6.022_140_76e23;
  const planck = 6.626_070_15e-34;
  
  // Nombres binaires
  const flags = 0b1010_0011_1100_0101;
  
  print('Population mondiale: $population');
  print('Adresse mémoire: ${memoryAddress.toRadixString(16)}');
}

// Note: Les séparateurs ne peuvent pas être utilisés:
// - Au début ou à la fin d'un nombre
// - Adjacent à d'autres caractères (., x, e)
// Invalide: _100, 100_, 1_.5, 0x_FF

2. Documentation Comment References

Support amélioré pour les références dans les commentaires de documentation.

/// Cette classe utilise [Future] et [Stream] pour les opérations async.
/// 
/// Voir aussi:
/// - [Future.value] pour créer une Future résolue
/// - [Stream.periodic] pour créer un Stream périodique
class AsyncProcessor {
  /// Traite les données de manière asynchrone
  Future<String> processData(Stream<int> input) async {
    // Implementation
    return 'Processed';
  }
}

3. Pub Workspaces

Nouvelle fonctionnalité pour gérer plusieurs packages dans un même repository.

# Fichier pubspec.yaml à la racine du workspace
name: my_workspace
workspace:
  - packages/core
  - packages/ui
  - packages/data

# Chaque sous-package a son propre pubspec.yaml
# mais partage la résolution des dépendances

4. Nouveau flag pub get

# Force l'utilisation exacte du lockfile
dart pub get --enforce-lockfile

# Utile pour les builds reproductibles et CI/CD

Dart 3.7 (Février 2025)

1. Variables Wildcard

Introduction des variables wildcard (non-liantes) avec le caractère _.

// Les variables wildcard peuvent être déclarées plusieurs fois
void processData(List<String> items) {
  // Ignorer certaines valeurs dans un pattern matching
  for (var (_, second, _) in getTriples()) {
    print('Second element: $second');
  }
  
  // Multiple déclarations sans collision
  var _ = computeExpensiveValue1(); // Ignoré
  var _ = computeExpensiveValue2(); // Ignoré aussi
  var _ = computeExpensiveValue3(); // Pas de conflit
  
  // Utile dans les callbacks où on ignore certains paramètres
  items.forEach((_, index) {
    print('Index: $index');
  });
}

// Pattern matching avec wildcards
String describePoint(Object point) {
  return switch (point) {
    (int x, int _) when x > 0 => 'Point sur l'axe X positif',
    (int _, int y) when y > 0 => 'Point sur l'axe Y positif',
    (int _, int _) => 'Point à l'origine ou ailleurs',
    _ => 'Pas un point valide',
  };
}

// Records avec wildcards
(String, int, bool) getUserInfo() => ('Alice', 25, true);

void main() {
  var (name, _, _) = getUserInfo(); // On ne garde que le nom
  print('User: $name');
}

2. Nouveau style de formatage ("Tall Style")

Le formateur a été largement réécrit pour supporter un nouveau style "tall".

// Avant Dart 3.7 (nécessitait des virgules manuelles)
Widget build(BuildContext context) {
  return Container(
    padding: EdgeInsets.all(16),
    child: Column(children: [
      Text('Title'),
      Text('Subtitle'),
      ElevatedButton(onPressed: () {}, child: Text('Click'))
    ]));
}

// Avec Dart 3.7 - Le formateur ajoute/enlève automatiquement les virgules
Widget build(BuildContext context) {
  return Container(
    padding: EdgeInsets.all(16),
    child: Column(
      children: [
        Text('Title'),
        Text('Subtitle'),
        ElevatedButton(
          onPressed: () {},
          child: Text('Click'),
        ),
      ],
    ),
  );
}

// Le formateur est maintenant lié à la version du langage
// Pour forcer le nouveau style:
// dart format --language-version=3.7 .

3. Nouvelles lints et quick fixes

// Nouveau lint: unnecessary_underscores
void example() {
  // ⚠️ Avertissement: underscore inutile pour une variable utilisée
  var _localVar = 42;
  print(_localVar); // La variable est utilisée, pas besoin de _
  
  // ✅ Correct: wildcard pour ignorer
  var _ = expensiveComputation();
  
  // ✅ Correct: variable privée de classe
  class MyClass {
    final int _privateField = 10;
  }
}

// Quick fix pour ajouter await manquant
Future<void> process() async {
  getData(); // ⚠️ Quick fix: Add 'await'
  // Devient: await getData();
}

// Conversion de else en else if
if (condition1) {
  // ...
} else { // Quick fix disponible
  if (condition2) {
    // ...
  }
}
// Devient: else if (condition2) { ... }

4. Compteurs de téléchargements sur pub.dev

// Les packages affichent maintenant:
// - Téléchargements mensuels
// - Graphique des téléchargements hebdomadaires
// - Téléchargements par version du package

// Utile pour évaluer la popularité et l'adoption
// des différentes versions d'un package

Dart 3.8 (Mai 2025)

1. Pub Workspaces (Stable)

La fonctionnalité workspaces devient stable pour gérer les monorepos.

# Structure d'un workspace
# /racine/pubspec.yaml
name: my_monorepo
environment:
  sdk: ^3.8.0

workspace:
  - packages/core
  - packages/ui
  - packages/data
  - apps/mobile
  - apps/web

# Avantages:
# - Résolution unique des dépendances
# - Meilleure performance de l'analyzer
# - Gestion simplifiée des versions
// Les packages du workspace peuvent se référencer entre eux
// packages/ui/lib/widgets.dart
import 'package:core/models.dart';
import 'package:data/repositories.dart';

class UserWidget extends StatelessWidget {
  final UserRepository repo; // Depuis package:data
  final User user; // Depuis package:core
  
  // ...
}

2. Doc Imports

Nouvelle syntaxe pour référencer des éléments externes dans la documentation sans les importer.

/// @docImport 'dart:async';
/// @docImport 'package:http/http.dart' as http;
library my_library;

/// Cette fonction retourne un [Future] qui se résout avec
/// le résultat d'une requête HTTP.
/// 
/// Utilise [http.Client] pour effectuer la requête.
/// En cas d'erreur, retourne [Future.error].
/// 
/// Exemple:
/// ```dart
/// final result = await fetchData();
/// ```
Future<String> fetchData() async {
  // Note: Future et http.Client sont référencés dans la doc
  // sans avoir besoin d'importer dart:async ou package:http
  return 'data';
}

3. Éléments null-aware pour les collections

Nouvelle syntaxe ? pour insérer conditionnellement des éléments dans les collections.

void main() {
  String? userName = getUserName(); // Peut être null
  int? age = getAge(); // Peut être null
  String? city;
  
  // Liste avec éléments null-aware
  var userInfo = [
    'User Info',
    ?userName, // Ajouté seulement si non-null
    ?age?.toString(), // Converti et ajouté si non-null
    ?city, // Ignoré si null
  ];
  // Résultat si userName="Alice", age=30, city=null:
  // ['User Info', 'Alice', '30']
  
  // Map avec entrées null-aware
  var config = {
    'debug': true,
    ?'username': userName, // Clé-valeur ajoutée si userName non-null
    ?'age': age,
    ?'city': city, // Entrée ignorée si city est null
  };
  
  // Set avec éléments null-aware
  var tags = {
    'required',
    ?optionalTag1,
    ?optionalTag2,
    ...?additionalTags, // Spread null-aware
  };
}

// Utilisation avec des conditions complexes
List<Widget> buildWidgets({String? title, String? subtitle}) {
  return [
    ?if (title != null) Text(title),
    ?if (subtitle != null) Text(subtitle, style: subtitleStyle),
    ?for (var item in items) 
      if (item.isVisible) Card(child: Text(item.name)),
  ];
}

4. Cross-compilation Linux

Support de la compilation croisée vers Linux x64 et ARM64.

# Compiler depuis macOS vers Linux x64
dart compile exe -t linux-x64 bin/server.dart

# Compiler depuis Windows vers Linux ARM64
dart compile exe -t linux-arm64 bin/app.dart

# Compilation native (comportement par défaut)
dart compile exe bin/app.dart

# Plateformes supportées:
# - Hôte: macOS, Windows, Linux (64-bit)
# - Cible: Linux x64, Linux ARM64

5. Nouvelles commandes et améliorations Pub

# Nouvelle commande: dart pub bump
# Incrémente automatiquement la version du package

# Version actuelle: 1.2.3
dart pub bump patch  # -> 1.2.4
dart pub bump minor  # -> 1.3.0
dart pub bump major  # -> 2.0.0
dart pub bump build  # -> 1.2.3+1

# Exemple avec options
dart pub bump minor --dry-run  # Aperçu sans modification
dart pub bump major --no-git-tag  # Sans créer de tag git
# Nouvel avertissement pour git status
dart pub publish
# ⚠️ Warning: Your git working tree is not clean.
# Consider committing or stashing your changes before publishing.

# Nouveau flag pour upgrade
dart pub upgrade --unlock-transitive
# Met à jour toutes les dépendances transitives
# au lieu de seulement les dépendances directes

6. Hot Reload pour le Web (Expérimental)

// Configuration pour activer le hot reload web
// Dans pubspec.yaml:
dev_dependencies:
  webdev: ^3.0.0

// Lancer avec hot reload
// dart run webdev serve --hot-reload

// Le code Dart est injecté dans l'application
// sans recharger la page complète
void main() {
  runApp(MyApp());
  
  // Les changements dans MyApp sont appliqués
  // instantanément pendant le développement
}

7. Améliorations de l'auto-complétion et assists

// Nouvel assist: Ajouter/Retirer les séparateurs de chiffres
const value = 1000000; // Quick action: Add digit separators
// Devient: 1_000_000

const formatted = 1_000_000; // Quick action: Remove digit separators  
// Devient: 1000000

// Nouvel assist: Inverser l'expression conditionnelle
if (isEnabled) {
  doSomething();
} else {
  doSomethingElse();
}
// Quick action: Invert conditional
// Devient:
if (!isEnabled) {
  doSomethingElse();
} else {
  doSomething();
}

Migration et bonnes pratiques

Mise à jour du SDK

# pubspec.yaml
environment:
  sdk: ^3.8.0  # Pour utiliser toutes les nouvelles fonctionnalités

Commandes de migration

# Vérifier les dépréciations
dart analyze

# Appliquer les fixes automatiques
dart fix --apply

# Formater avec le nouveau style (3.7+)
dart format .

# Migrer vers package:web (depuis dart:html)
dart pub add web
dart fix --apply

Ordre de migration recommandé

  1. Dart 3.5: Migrer de dart:html vers package:web
  2. Dart 3.6: Adopter les séparateurs de chiffres pour les grandes constantes numériques
  3. Dart 3.7: Utiliser les variables wildcard et adopter le nouveau formatage
  4. Dart 3.8: Implémenter les workspaces pour les monorepos et utiliser les éléments null-aware

Résumé des changements majeurs

Version Fonctionnalité principale Impact
3.5 Interopérabilité Web/Native Migration de dart:html vers package:web
3.6 Séparateurs de chiffres Meilleure lisibilité du code
3.7 Variables wildcard Code plus expressif et concis
3.8 Workspaces & null-aware collections Meilleure gestion des monorepos et collections

Ces versions représentent une évolution significative de Dart, avec un focus sur l'interopérabilité, la productivité des développeurs, et la modernisation du langage. La migration est généralement simple grâce aux outils automatiques fournis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment