[go_router_builder] Adds support for enhanced enums. (#2395)

diff --git a/packages/go_router_builder/CHANGELOG.md b/packages/go_router_builder/CHANGELOG.md
index b04d17c..2ab6014 100644
--- a/packages/go_router_builder/CHANGELOG.md
+++ b/packages/go_router_builder/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.0.12
+
+* Adds support for enhanced enums. [#105876](https://github.com/flutter/flutter/issues/105876).
+
 ## 1.0.11
 
 * Replaces mentions of the deprecated `GoRouteData.buildPage` with `GoRouteData.buildPageWithState`.
diff --git a/packages/go_router_builder/example/lib/all_types.dart b/packages/go_router_builder/example/lib/all_types.dart
index b9a35f9..8197697 100644
--- a/packages/go_router_builder/example/lib/all_types.dart
+++ b/packages/go_router_builder/example/lib/all_types.dart
@@ -11,150 +11,353 @@
 
 part 'all_types.g.dart';
 
-@TypedGoRoute<AllTypesRoute>(
-  path: '/:requiredBigIntField/:requiredBoolField/:requiredDateTimeField'
-      '/:requiredDoubleField/:requiredEnumField/:requiredIntField'
-      '/:requiredNumField/:requiredStringField/:requiredUriField',
-)
+@TypedGoRoute<AllTypesBaseRoute>(path: '/', routes: <TypedGoRoute<GoRouteData>>[
+  TypedGoRoute<BigIntRoute>(path: 'big-int-route/:requiredBigIntField'),
+  TypedGoRoute<BoolRoute>(path: 'bool-route/:requiredBoolField'),
+  TypedGoRoute<DateTimeRoute>(path: 'date-time-route/:requiredDateTimeField'),
+  TypedGoRoute<DoubleRoute>(path: 'double-route/:requiredDoubleField'),
+  TypedGoRoute<IntRoute>(path: 'int-route/:requiredIntField'),
+  TypedGoRoute<NumRoute>(path: 'num-route/:requiredNumField'),
+  TypedGoRoute<DoubleRoute>(path: 'double-route/:requiredDoubleField'),
+  TypedGoRoute<EnumRoute>(path: 'enum-route/:requiredEnumField'),
+  TypedGoRoute<EnhancedEnumRoute>(
+      path: 'enhanced-enum-route/:requiredEnumField'),
+  TypedGoRoute<StringRoute>(path: 'string-route/:requiredStringField'),
+  TypedGoRoute<UriRoute>(path: 'uri-route/:requiredUriField'),
+])
 @immutable
-class AllTypesRoute extends GoRouteData {
-  const AllTypesRoute({
+class AllTypesBaseRoute extends GoRouteData {
+  const AllTypesBaseRoute();
+
+  @override
+  Widget build(BuildContext context) => const BasePage<void>(
+        dataTitle: 'Root',
+        param: null,
+      );
+}
+
+class BigIntRoute extends GoRouteData {
+  BigIntRoute({
     required this.requiredBigIntField,
-    required this.requiredBoolField,
-    required this.requiredDateTimeField,
-    required this.requiredDoubleField,
-    required this.requiredEnumField,
-    required this.requiredIntField,
-    required this.requiredNumField,
-    required this.requiredStringField,
-    required this.requiredUriField,
     this.bigIntField,
-    this.boolField,
-    this.dateTimeField,
-    this.doubleField,
-    this.enumField,
-    this.intField,
-    this.numField,
-    this.stringField,
-    this.uriField,
   });
 
   final BigInt requiredBigIntField;
-  final bool requiredBoolField;
-  final DateTime requiredDateTimeField;
-  final double requiredDoubleField;
-  final PersonDetails requiredEnumField;
-  final int requiredIntField;
-  final num requiredNumField;
-  final String requiredStringField;
-  final Uri requiredUriField;
-
   final BigInt? bigIntField;
+
+  @override
+  Widget build(BuildContext context) => BasePage<BigInt>(
+        dataTitle: 'BigIntRoute',
+        param: requiredBigIntField,
+        queryParam: bigIntField,
+      );
+
+  Widget drawerTile(BuildContext context) => ListTile(
+        title: const Text('BigIntRoute'),
+        onTap: () => go(context),
+        selected: GoRouter.of(context).location == location,
+      );
+}
+
+class BoolRoute extends GoRouteData {
+  BoolRoute({
+    required this.requiredBoolField,
+    this.boolField,
+  });
+
+  final bool requiredBoolField;
   final bool? boolField;
+
+  @override
+  Widget build(BuildContext context) => BasePage<bool>(
+        dataTitle: 'BoolRoute',
+        param: requiredBoolField,
+        queryParam: boolField,
+      );
+
+  Widget drawerTile(BuildContext context) => ListTile(
+        title: const Text('BoolRoute'),
+        onTap: () => go(context),
+        selected: GoRouter.of(context).location == location,
+      );
+}
+
+class DateTimeRoute extends GoRouteData {
+  DateTimeRoute({
+    required this.requiredDateTimeField,
+    this.dateTimeField,
+  });
+
+  final DateTime requiredDateTimeField;
   final DateTime? dateTimeField;
+
+  @override
+  Widget build(BuildContext context) => BasePage<DateTime>(
+        dataTitle: 'DateTimeRoute',
+        param: requiredDateTimeField,
+        queryParam: dateTimeField,
+      );
+
+  Widget drawerTile(BuildContext context) => ListTile(
+        title: const Text('DateTimeRoute'),
+        onTap: () => go(context),
+        selected: GoRouter.of(context).location == location,
+      );
+}
+
+class DoubleRoute extends GoRouteData {
+  DoubleRoute({
+    required this.requiredDoubleField,
+    this.doubleField,
+  });
+
+  final double requiredDoubleField;
   final double? doubleField;
-  final PersonDetails? enumField;
+
+  @override
+  Widget build(BuildContext context) => BasePage<double>(
+        dataTitle: 'DoubleRoute',
+        param: requiredDoubleField,
+        queryParam: doubleField,
+      );
+
+  Widget drawerTile(BuildContext context) => ListTile(
+        title: const Text('DoubleRoute'),
+        onTap: () => go(context),
+        selected: GoRouter.of(context).location == location,
+      );
+}
+
+class IntRoute extends GoRouteData {
+  IntRoute({
+    required this.requiredIntField,
+    this.intField,
+  });
+
+  final int requiredIntField;
   final int? intField;
+
+  @override
+  Widget build(BuildContext context) => BasePage<int>(
+        dataTitle: 'IntRoute',
+        param: requiredIntField,
+        queryParam: intField,
+      );
+
+  Widget drawerTile(BuildContext context) => ListTile(
+        title: const Text('IntRoute'),
+        onTap: () => go(context),
+        selected: GoRouter.of(context).location == location,
+      );
+}
+
+class NumRoute extends GoRouteData {
+  NumRoute({
+    required this.requiredNumField,
+    this.numField,
+  });
+
+  final num requiredNumField;
   final num? numField;
+
+  @override
+  Widget build(BuildContext context) => BasePage<num>(
+        dataTitle: 'NumRoute',
+        param: requiredNumField,
+        queryParam: numField,
+      );
+
+  Widget drawerTile(BuildContext context) => ListTile(
+        title: const Text('NumRoute'),
+        onTap: () => go(context),
+        selected: GoRouter.of(context).location == location,
+      );
+}
+
+class EnumRoute extends GoRouteData {
+  EnumRoute({
+    required this.requiredEnumField,
+    this.enumField,
+  });
+
+  final PersonDetails requiredEnumField;
+  final PersonDetails? enumField;
+
+  @override
+  Widget build(BuildContext context) => BasePage<PersonDetails>(
+        dataTitle: 'EnumRoute',
+        param: requiredEnumField,
+        queryParam: enumField,
+      );
+
+  Widget drawerTile(BuildContext context) => ListTile(
+        title: const Text('EnumRoute'),
+        onTap: () => go(context),
+        selected: GoRouter.of(context).location == location,
+      );
+}
+
+class EnhancedEnumRoute extends GoRouteData {
+  EnhancedEnumRoute({
+    required this.requiredEnumField,
+    this.enumField,
+  });
+
+  final SportDetails requiredEnumField;
+  final SportDetails? enumField;
+
+  @override
+  Widget build(BuildContext context) => BasePage<SportDetails>(
+        dataTitle: 'EnhancedEnumRoute',
+        param: requiredEnumField,
+        queryParam: enumField,
+      );
+
+  Widget drawerTile(BuildContext context) => ListTile(
+        title: const Text('EnhancedEnumRoute'),
+        onTap: () => go(context),
+        selected: GoRouter.of(context).location == location,
+      );
+}
+
+class StringRoute extends GoRouteData {
+  StringRoute({
+    required this.requiredStringField,
+    this.stringField,
+  });
+
+  final String requiredStringField;
   final String? stringField;
+
+  @override
+  Widget build(BuildContext context) => BasePage<String>(
+        dataTitle: 'StringRoute',
+        param: requiredStringField,
+        queryParam: stringField,
+      );
+
+  Widget drawerTile(BuildContext context) => ListTile(
+        title: const Text('StringRoute'),
+        onTap: () => go(context),
+        selected: GoRouter.of(context).location == location,
+      );
+}
+
+class UriRoute extends GoRouteData {
+  UriRoute({
+    required this.requiredUriField,
+    this.uriField,
+  });
+
+  final Uri requiredUriField;
   final Uri? uriField;
 
   @override
+  Widget build(BuildContext context) => BasePage<Uri>(
+        dataTitle: 'UriRoute',
+        param: requiredUriField,
+        queryParam: uriField,
+      );
+
+  Widget drawerTile(BuildContext context) => ListTile(
+        title: const Text('UriRoute'),
+        onTap: () => go(context),
+        selected: GoRouter.of(context).location == location,
+      );
+}
+
+class BasePage<T> extends StatelessWidget {
+  const BasePage({
+    required this.dataTitle,
+    required this.param,
+    this.queryParam,
+    super.key,
+  });
+
+  final String dataTitle;
+  final T param;
+  final T? queryParam;
+
+  @override
   Widget build(BuildContext context) => Scaffold(
+        appBar: AppBar(
+          title: const Text('Go router typed routes'),
+        ),
+        drawer: Drawer(
+            child: ListView(
+          children: <Widget>[
+            BigIntRoute(
+              requiredBigIntField: BigInt.two,
+              bigIntField: BigInt.zero,
+            ).drawerTile(context),
+            BoolRoute(
+              requiredBoolField: true,
+              boolField: false,
+            ).drawerTile(context),
+            DateTimeRoute(
+              requiredDateTimeField: DateTime(1970),
+              dateTimeField: DateTime(0),
+            ).drawerTile(context),
+            DoubleRoute(
+              requiredDoubleField: 3.14,
+              doubleField: -3.14,
+            ).drawerTile(context),
+            IntRoute(
+              requiredIntField: 42,
+              intField: -42,
+            ).drawerTile(context),
+            NumRoute(
+              requiredNumField: 2.71828,
+              numField: -2.71828,
+            ).drawerTile(context),
+            StringRoute(
+              requiredStringField: r'$!/#bob%%20',
+              stringField: r'$!/#bob%%20',
+            ).drawerTile(context),
+            EnumRoute(
+              requiredEnumField: PersonDetails.favoriteSport,
+              enumField: PersonDetails.favoriteFood,
+            ).drawerTile(context),
+            EnhancedEnumRoute(
+              requiredEnumField: SportDetails.football,
+              enumField: SportDetails.volleyball,
+            ).drawerTile(context),
+            UriRoute(
+              requiredUriField: Uri.parse('https://dart.dev'),
+              uriField: Uri.parse('https://dart.dev'),
+            ).drawerTile(context),
+          ],
+        )),
         body: Center(
           child: Column(
             mainAxisSize: MainAxisSize.min,
             children: <Widget>[
-              const Text('built!'),
-              SelectableText(location),
+              const Text('Built!'),
+              Text(dataTitle),
+              Text('Param: $param'),
+              Text('Query param: $queryParam'),
+              SelectableText(GoRouter.of(context).location),
             ],
           ),
         ),
       );
-
-  @override
-  int get hashCode => Object.hashAll(_items);
-
-  @override
-  bool operator ==(Object other) {
-    if (other is AllTypesRoute) {
-      final List<Object?> mine = _items;
-      final List<Object?> theirs = other._items;
-      for (int i = 0; i < mine.length; i++) {
-        if (mine[i] != theirs[i]) {
-          return false;
-        }
-      }
-    }
-    return true;
-  }
-
-  List<Object?> get _items => <Object?>[
-        requiredBigIntField,
-        requiredBoolField,
-        requiredDateTimeField,
-        requiredDoubleField,
-        requiredEnumField,
-        requiredIntField,
-        requiredNumField,
-        requiredStringField,
-        requiredUriField,
-        bigIntField,
-        boolField,
-        dateTimeField,
-        doubleField,
-        enumField,
-        intField,
-        numField,
-        stringField,
-        uriField,
-      ];
 }
 
 void main() => runApp(AllTypesApp());
 
 class AllTypesApp extends StatelessWidget {
-  AllTypesApp({Key? key}) : super(key: key);
+  AllTypesApp({super.key});
 
   @override
   Widget build(BuildContext context) => MaterialApp.router(
         routeInformationParser: _router.routeInformationParser,
         routerDelegate: _router.routerDelegate,
+        routeInformationProvider: _router.routeInformationProvider,
       );
 
   late final GoRouter _router = GoRouter(
     debugLogDiagnostics: true,
     routes: $appRoutes,
-
-    // redirect to the login page if the user is not logged in
-    redirect: (GoRouterState state) {
-      if (state.location == '/') {
-        final String location = AllTypesRoute(
-          requiredBigIntField: BigInt.two,
-          requiredBoolField: true,
-          requiredDateTimeField: DateTime.now(),
-          requiredDoubleField: 3.14,
-          requiredEnumField: PersonDetails.favoriteSport,
-          requiredIntField: -42,
-          requiredNumField: 3.15,
-          requiredStringField: r'$!/#bob%%20',
-          requiredUriField: Uri.parse('https://dart.dev'),
-          bigIntField: BigInt.zero,
-          boolField: false,
-          dateTimeField: DateTime(0),
-          doubleField: 3.14,
-          enumField: PersonDetails.favoriteSport,
-          intField: -42,
-          numField: 3.15,
-          stringField: r'$!/#bob%%20',
-          uriField: Uri.parse('https://dart.dev'),
-        ).location;
-
-        return location;
-      }
-
-      // no need to redirect at all
-      return null;
-    },
+    initialLocation: const AllTypesBaseRoute().location,
   );
 }
diff --git a/packages/go_router_builder/example/lib/all_types.g.dart b/packages/go_router_builder/example/lib/all_types.g.dart
index 2643537..4aeb417 100644
--- a/packages/go_router_builder/example/lib/all_types.g.dart
+++ b/packages/go_router_builder/example/lib/all_types.g.dart
@@ -9,57 +9,256 @@
 // **************************************************************************
 
 List<GoRoute> get $appRoutes => [
-      $allTypesRoute,
+      $allTypesBaseRoute,
     ];
 
-GoRoute get $allTypesRoute => GoRouteData.$route(
-      path:
-          '/:requiredBigIntField/:requiredBoolField/:requiredDateTimeField/:requiredDoubleField/:requiredEnumField/:requiredIntField/:requiredNumField/:requiredStringField/:requiredUriField',
-      factory: $AllTypesRouteExtension._fromState,
+GoRoute get $allTypesBaseRoute => GoRouteData.$route(
+      path: '/',
+      factory: $AllTypesBaseRouteExtension._fromState,
+      routes: [
+        GoRouteData.$route(
+          path: 'big-int-route/:requiredBigIntField',
+          factory: $BigIntRouteExtension._fromState,
+        ),
+        GoRouteData.$route(
+          path: 'bool-route/:requiredBoolField',
+          factory: $BoolRouteExtension._fromState,
+        ),
+        GoRouteData.$route(
+          path: 'date-time-route/:requiredDateTimeField',
+          factory: $DateTimeRouteExtension._fromState,
+        ),
+        GoRouteData.$route(
+          path: 'double-route/:requiredDoubleField',
+          factory: $DoubleRouteExtension._fromState,
+        ),
+        GoRouteData.$route(
+          path: 'int-route/:requiredIntField',
+          factory: $IntRouteExtension._fromState,
+        ),
+        GoRouteData.$route(
+          path: 'num-route/:requiredNumField',
+          factory: $NumRouteExtension._fromState,
+        ),
+        GoRouteData.$route(
+          path: 'double-route/:requiredDoubleField',
+          factory: $DoubleRouteExtension._fromState,
+        ),
+        GoRouteData.$route(
+          path: 'enum-route/:requiredEnumField',
+          factory: $EnumRouteExtension._fromState,
+        ),
+        GoRouteData.$route(
+          path: 'enhanced-enum-route/:requiredEnumField',
+          factory: $EnhancedEnumRouteExtension._fromState,
+        ),
+        GoRouteData.$route(
+          path: 'string-route/:requiredStringField',
+          factory: $StringRouteExtension._fromState,
+        ),
+        GoRouteData.$route(
+          path: 'uri-route/:requiredUriField',
+          factory: $UriRouteExtension._fromState,
+        ),
+      ],
     );
 
-extension $AllTypesRouteExtension on AllTypesRoute {
-  static AllTypesRoute _fromState(GoRouterState state) => AllTypesRoute(
+extension $AllTypesBaseRouteExtension on AllTypesBaseRoute {
+  static AllTypesBaseRoute _fromState(GoRouterState state) =>
+      const AllTypesBaseRoute();
+
+  String get location => GoRouteData.$location(
+        '/',
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+extension $BigIntRouteExtension on BigIntRoute {
+  static BigIntRoute _fromState(GoRouterState state) => BigIntRoute(
         requiredBigIntField: BigInt.parse(state.params['requiredBigIntField']!),
-        requiredBoolField: _$boolConverter(state.params['requiredBoolField']!),
-        requiredDateTimeField:
-            DateTime.parse(state.params['requiredDateTimeField']!),
-        requiredDoubleField: double.parse(state.params['requiredDoubleField']!),
-        requiredEnumField: _$PersonDetailsEnumMap
-            ._$fromName(state.params['requiredEnumField']!),
-        requiredIntField: int.parse(state.params['requiredIntField']!),
-        requiredNumField: num.parse(state.params['requiredNumField']!),
-        requiredStringField: state.params['requiredStringField']!,
-        requiredUriField: Uri.parse(state.params['requiredUriField']!),
         bigIntField:
             _$convertMapValue('big-int-field', state.queryParams, BigInt.parse),
+      );
+
+  String get location => GoRouteData.$location(
+        '/big-int-route/${Uri.encodeComponent(requiredBigIntField.toString())}',
+        queryParams: {
+          if (bigIntField != null) 'big-int-field': bigIntField!.toString(),
+        },
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+extension $BoolRouteExtension on BoolRoute {
+  static BoolRoute _fromState(GoRouterState state) => BoolRoute(
+        requiredBoolField: _$boolConverter(state.params['requiredBoolField']!),
         boolField:
             _$convertMapValue('bool-field', state.queryParams, _$boolConverter),
+      );
+
+  String get location => GoRouteData.$location(
+        '/bool-route/${Uri.encodeComponent(requiredBoolField.toString())}',
+        queryParams: {
+          if (boolField != null) 'bool-field': boolField!.toString(),
+        },
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+extension $DateTimeRouteExtension on DateTimeRoute {
+  static DateTimeRoute _fromState(GoRouterState state) => DateTimeRoute(
+        requiredDateTimeField:
+            DateTime.parse(state.params['requiredDateTimeField']!),
         dateTimeField: _$convertMapValue(
             'date-time-field', state.queryParams, DateTime.parse),
+      );
+
+  String get location => GoRouteData.$location(
+        '/date-time-route/${Uri.encodeComponent(requiredDateTimeField.toString())}',
+        queryParams: {
+          if (dateTimeField != null)
+            'date-time-field': dateTimeField!.toString(),
+        },
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+extension $DoubleRouteExtension on DoubleRoute {
+  static DoubleRoute _fromState(GoRouterState state) => DoubleRoute(
+        requiredDoubleField: double.parse(state.params['requiredDoubleField']!),
         doubleField:
             _$convertMapValue('double-field', state.queryParams, double.parse),
+      );
+
+  String get location => GoRouteData.$location(
+        '/double-route/${Uri.encodeComponent(requiredDoubleField.toString())}',
+        queryParams: {
+          if (doubleField != null) 'double-field': doubleField!.toString(),
+        },
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+extension $IntRouteExtension on IntRoute {
+  static IntRoute _fromState(GoRouterState state) => IntRoute(
+        requiredIntField: int.parse(state.params['requiredIntField']!),
+        intField: _$convertMapValue('int-field', state.queryParams, int.parse),
+      );
+
+  String get location => GoRouteData.$location(
+        '/int-route/${Uri.encodeComponent(requiredIntField.toString())}',
+        queryParams: {
+          if (intField != null) 'int-field': intField!.toString(),
+        },
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+extension $NumRouteExtension on NumRoute {
+  static NumRoute _fromState(GoRouterState state) => NumRoute(
+        requiredNumField: num.parse(state.params['requiredNumField']!),
+        numField: _$convertMapValue('num-field', state.queryParams, num.parse),
+      );
+
+  String get location => GoRouteData.$location(
+        '/num-route/${Uri.encodeComponent(requiredNumField.toString())}',
+        queryParams: {
+          if (numField != null) 'num-field': numField!.toString(),
+        },
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+extension $EnumRouteExtension on EnumRoute {
+  static EnumRoute _fromState(GoRouterState state) => EnumRoute(
+        requiredEnumField: _$PersonDetailsEnumMap
+            ._$fromName(state.params['requiredEnumField']!),
         enumField: _$convertMapValue(
             'enum-field', state.queryParams, _$PersonDetailsEnumMap._$fromName),
-        intField: _$convertMapValue('int-field', state.queryParams, int.parse),
-        numField: _$convertMapValue('num-field', state.queryParams, num.parse),
+      );
+
+  String get location => GoRouteData.$location(
+        '/enum-route/${Uri.encodeComponent(_$PersonDetailsEnumMap[requiredEnumField]!)}',
+        queryParams: {
+          if (enumField != null)
+            'enum-field': _$PersonDetailsEnumMap[enumField!]!,
+        },
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+extension $EnhancedEnumRouteExtension on EnhancedEnumRoute {
+  static EnhancedEnumRoute _fromState(GoRouterState state) => EnhancedEnumRoute(
+        requiredEnumField: _$SportDetailsEnumMap
+            ._$fromName(state.params['requiredEnumField']!),
+        enumField: _$convertMapValue(
+            'enum-field', state.queryParams, _$SportDetailsEnumMap._$fromName),
+      );
+
+  String get location => GoRouteData.$location(
+        '/enhanced-enum-route/${Uri.encodeComponent(_$SportDetailsEnumMap[requiredEnumField]!)}',
+        queryParams: {
+          if (enumField != null)
+            'enum-field': _$SportDetailsEnumMap[enumField!]!,
+        },
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+extension $StringRouteExtension on StringRoute {
+  static StringRoute _fromState(GoRouterState state) => StringRoute(
+        requiredStringField: state.params['requiredStringField']!,
         stringField: state.queryParams['string-field'],
+      );
+
+  String get location => GoRouteData.$location(
+        '/string-route/${Uri.encodeComponent(requiredStringField)}',
+        queryParams: {
+          if (stringField != null) 'string-field': stringField!,
+        },
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+extension $UriRouteExtension on UriRoute {
+  static UriRoute _fromState(GoRouterState state) => UriRoute(
+        requiredUriField: Uri.parse(state.params['requiredUriField']!),
         uriField: _$convertMapValue('uri-field', state.queryParams, Uri.parse),
       );
 
   String get location => GoRouteData.$location(
-        '/${Uri.encodeComponent(requiredBigIntField.toString())}/${Uri.encodeComponent(requiredBoolField.toString())}/${Uri.encodeComponent(requiredDateTimeField.toString())}/${Uri.encodeComponent(requiredDoubleField.toString())}/${Uri.encodeComponent(_$PersonDetailsEnumMap[requiredEnumField]!)}/${Uri.encodeComponent(requiredIntField.toString())}/${Uri.encodeComponent(requiredNumField.toString())}/${Uri.encodeComponent(requiredStringField)}/${Uri.encodeComponent(requiredUriField.toString())}',
+        '/uri-route/${Uri.encodeComponent(requiredUriField.toString())}',
         queryParams: {
-          if (bigIntField != null) 'big-int-field': bigIntField!.toString(),
-          if (boolField != null) 'bool-field': boolField!.toString(),
-          if (dateTimeField != null)
-            'date-time-field': dateTimeField!.toString(),
-          if (doubleField != null) 'double-field': doubleField!.toString(),
-          if (enumField != null)
-            'enum-field': _$PersonDetailsEnumMap[enumField!]!,
-          if (intField != null) 'int-field': intField!.toString(),
-          if (numField != null) 'num-field': numField!.toString(),
-          if (stringField != null) 'string-field': stringField!,
           if (uriField != null) 'uri-field': uriField!.toString(),
         },
       );
@@ -75,6 +274,13 @@
   PersonDetails.favoriteSport: 'favorite-sport',
 };
 
+const _$SportDetailsEnumMap = {
+  SportDetails.volleyball: 'volleyball',
+  SportDetails.football: 'football',
+  SportDetails.tennis: 'tennis',
+  SportDetails.hockey: 'hockey',
+};
+
 T? _$convertMapValue<T>(
   String key,
   Map<String, String> map,
diff --git a/packages/go_router_builder/example/lib/main.dart b/packages/go_router_builder/example/lib/main.dart
index e58a5ac..1023f8c 100644
--- a/packages/go_router_builder/example/lib/main.dart
+++ b/packages/go_router_builder/example/lib/main.dart
@@ -15,7 +15,7 @@
 void main() => runApp(App());
 
 class App extends StatelessWidget {
-  App({Key? key}) : super(key: key);
+  App({super.key});
 
   final LoginInfo loginInfo = LoginInfo();
   static const String title = 'GoRouter Example: Named Routes';
@@ -148,7 +148,7 @@
 }
 
 class HomeScreen extends StatelessWidget {
-  const HomeScreen({Key? key}) : super(key: key);
+  const HomeScreen({super.key});
 
   @override
   Widget build(BuildContext context) {
@@ -184,7 +184,7 @@
 }
 
 class FamilyScreen extends StatelessWidget {
-  const FamilyScreen({required this.family, Key? key}) : super(key: key);
+  const FamilyScreen({required this.family, super.key});
   final Family family;
 
   @override
@@ -203,8 +203,7 @@
 }
 
 class PersonScreen extends StatelessWidget {
-  const PersonScreen({required this.family, required this.person, Key? key})
-      : super(key: key);
+  const PersonScreen({required this.family, required this.person, super.key});
 
   final Family family;
   final Person person;
@@ -250,8 +249,8 @@
     required this.person,
     required this.detailsKey,
     this.extra,
-    Key? key,
-  }) : super(key: key);
+    super.key,
+  });
 
   final Family family;
   final Person person;
@@ -278,7 +277,7 @@
 }
 
 class LoginScreen extends StatelessWidget {
-  const LoginScreen({this.from, Key? key}) : super(key: key);
+  const LoginScreen({this.from, super.key});
   final String? from;
 
   @override
diff --git a/packages/go_router_builder/example/lib/shared/data.dart b/packages/go_router_builder/example/lib/shared/data.dart
index 3f017fc..edc3f20 100644
--- a/packages/go_router_builder/example/lib/shared/data.dart
+++ b/packages/go_router_builder/example/lib/shared/data.dart
@@ -14,6 +14,46 @@
   favoriteSport,
 }
 
+enum SportDetails {
+  volleyball(
+    imageUrl: '/sportdetails/url/volleyball.jpg',
+    playerPerTeam: 6,
+    accessory: null,
+    hasNet: true,
+  ),
+  football(
+    imageUrl: '/sportdetails/url/Football.jpg',
+    playerPerTeam: 11,
+    accessory: null,
+    hasNet: true,
+  ),
+  tennis(
+    imageUrl: '/sportdetails/url/tennis.jpg',
+    playerPerTeam: 2,
+    accessory: 'Rackets',
+    hasNet: true,
+  ),
+  hockey(
+    imageUrl: '/sportdetails/url/hockey.jpg',
+    playerPerTeam: 6,
+    accessory: 'Hockey sticks',
+    hasNet: true,
+  ),
+  ;
+
+  const SportDetails({
+    required this.accessory,
+    required this.hasNet,
+    required this.imageUrl,
+    required this.playerPerTeam,
+  });
+
+  final String imageUrl;
+  final int playerPerTeam;
+  final String? accessory;
+  final bool hasNet;
+}
+
 /// sample Person class
 class Person {
   Person({
diff --git a/packages/go_router_builder/example/lib/simple_example.dart b/packages/go_router_builder/example/lib/simple_example.dart
index 1597104..9657475 100644
--- a/packages/go_router_builder/example/lib/simple_example.dart
+++ b/packages/go_router_builder/example/lib/simple_example.dart
@@ -14,7 +14,7 @@
 void main() => runApp(App());
 
 class App extends StatelessWidget {
-  App({Key? key}) : super(key: key);
+  App({super.key});
 
   @override
   Widget build(BuildContext context) => MaterialApp.router(
@@ -50,7 +50,7 @@
 }
 
 class HomeScreen extends StatelessWidget {
-  const HomeScreen({Key? key}) : super(key: key);
+  const HomeScreen({super.key});
 
   @override
   Widget build(BuildContext context) => Scaffold(
@@ -68,7 +68,7 @@
 }
 
 class FamilyScreen extends StatelessWidget {
-  const FamilyScreen({required this.family, Key? key}) : super(key: key);
+  const FamilyScreen({required this.family, super.key});
   final Family family;
 
   @override
diff --git a/packages/go_router_builder/example/pubspec.yaml b/packages/go_router_builder/example/pubspec.yaml
index 90edafe..4a4f72f 100644
--- a/packages/go_router_builder/example/pubspec.yaml
+++ b/packages/go_router_builder/example/pubspec.yaml
@@ -3,7 +3,7 @@
 publish_to: none
 
 environment:
-  sdk: ">=2.14.0 <3.0.0"
+  sdk: ">=2.17.0 <3.0.0"
 
 dependencies:
   flutter:
diff --git a/packages/go_router_builder/example/test/all_types_test.dart b/packages/go_router_builder/example/test/all_types_test.dart
new file mode 100644
index 0000000..4a0cac6
--- /dev/null
+++ b/packages/go_router_builder/example/test/all_types_test.dart
@@ -0,0 +1,114 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// import 'package:flutter/material.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:go_router_builder_example/all_types.dart';
+import 'package:go_router_builder_example/shared/data.dart';
+
+void main() {
+  testWidgets('Test typed route navigation', (WidgetTester tester) async {
+    await tester.pumpWidget(AllTypesApp());
+
+    final ScaffoldState scaffoldState =
+        tester.firstState(find.byType(Scaffold));
+
+    BigIntRoute(
+      requiredBigIntField: BigInt.from(4),
+      bigIntField: BigInt.from(8),
+    ).go(scaffoldState.context);
+    await tester.pumpAndSettle();
+    expect(find.text('BigIntRoute'), findsOneWidget);
+    expect(find.text('Param: 4'), findsOneWidget);
+    expect(find.text('Query param: 8'), findsOneWidget);
+
+    BoolRoute(
+      requiredBoolField: false,
+      boolField: true,
+    ).go(scaffoldState.context);
+    await tester.pumpAndSettle();
+    expect(find.text('BoolRoute'), findsOneWidget);
+    expect(find.text('Param: false'), findsOneWidget);
+    expect(find.text('Query param: true'), findsOneWidget);
+
+    final DateTime param = DateTime.now();
+    final DateTime query = DateTime(2017, 9, 7, 17, 30);
+    DateTimeRoute(
+      requiredDateTimeField: param,
+      dateTimeField: query,
+    ).go(scaffoldState.context);
+    await tester.pumpAndSettle();
+    expect(find.text('DateTimeRoute'), findsOneWidget);
+    expect(find.text('Param: $param'), findsOneWidget);
+    expect(find.text('Query param: $query'), findsOneWidget);
+
+    DoubleRoute(
+      requiredDoubleField: 3.14,
+      doubleField: -3.14,
+    ).go(scaffoldState.context);
+    await tester.pumpAndSettle();
+    expect(find.text('DoubleRoute'), findsOneWidget);
+    expect(find.text('Param: 3.14'), findsOneWidget);
+    expect(find.text('Query param: -3.14'), findsOneWidget);
+
+    IntRoute(
+      requiredIntField: 65,
+      intField: -65,
+    ).go(scaffoldState.context);
+    await tester.pumpAndSettle();
+    expect(find.text('IntRoute'), findsOneWidget);
+    expect(find.text('Param: 65'), findsOneWidget);
+    expect(find.text('Query param: -65'), findsOneWidget);
+
+    NumRoute(
+      requiredNumField: 987.32,
+      numField: -987.32,
+    ).go(scaffoldState.context);
+    await tester.pumpAndSettle();
+    expect(find.text('NumRoute'), findsOneWidget);
+    expect(find.text('Param: 987.32'), findsOneWidget);
+    expect(find.text('Query param: -987.32'), findsOneWidget);
+
+    StringRoute(
+      requiredStringField: r'Tytire tu patulae recubans sub tegmine fagi.',
+      stringField: r'Tytire tu patulae recubans sub tegmine fagi.',
+    ).go(scaffoldState.context);
+    await tester.pumpAndSettle();
+    expect(find.text('StringRoute'), findsOneWidget);
+    expect(find.text('Param: Tytire tu patulae recubans sub tegmine fagi.'),
+        findsOneWidget);
+    expect(
+        find.text('Query param: Tytire tu patulae recubans sub tegmine fagi.'),
+        findsOneWidget);
+
+    EnumRoute(
+      requiredEnumField: PersonDetails.favoriteFood,
+      enumField: PersonDetails.favoriteSport,
+    ).go(scaffoldState.context);
+    await tester.pumpAndSettle();
+    expect(find.text('EnumRoute'), findsOneWidget);
+    expect(find.text('Param: PersonDetails.favoriteFood'), findsOneWidget);
+    expect(
+        find.text('Query param: PersonDetails.favoriteSport'), findsOneWidget);
+
+    EnhancedEnumRoute(
+      requiredEnumField: SportDetails.football,
+      enumField: SportDetails.hockey,
+    ).go(scaffoldState.context);
+    await tester.pumpAndSettle();
+    expect(find.text('EnhancedEnumRoute'), findsOneWidget);
+    expect(find.text('Param: SportDetails.football'), findsOneWidget);
+    expect(find.text('Query param: SportDetails.hockey'), findsOneWidget);
+
+    UriRoute(
+      requiredUriField: Uri.parse('https://dart.dev'),
+      uriField: Uri.parse('https://dart.dev'),
+    ).go(scaffoldState.context);
+    await tester.pumpAndSettle();
+    expect(find.text('UriRoute'), findsOneWidget);
+    expect(find.text('Param: https://dart.dev'), findsOneWidget);
+    expect(find.text('Query param: https://dart.dev'), findsOneWidget);
+  });
+}
diff --git a/packages/go_router_builder/lib/src/route_config.dart b/packages/go_router_builder/lib/src/route_config.dart
index 49ebc5d..f058a2c 100644
--- a/packages/go_router_builder/lib/src/route_config.dart
+++ b/packages/go_router_builder/lib/src/route_config.dart
@@ -368,7 +368,7 @@
   final StringBuffer buffer = StringBuffer('const ${enumMapName(type)} = {');
 
   for (final FieldElement enumField in type.element2.fields
-      .where((FieldElement element) => !element.isSynthetic)) {
+      .where((FieldElement element) => element.isEnumConstant)) {
     buffer.writeln(
       '$enumName.${enumField.name}: ${escapeDartString(enumField.name.kebab)},',
     );
diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml
index ac221ea..81781eb 100644
--- a/packages/go_router_builder/pubspec.yaml
+++ b/packages/go_router_builder/pubspec.yaml
@@ -2,7 +2,7 @@
 description: >-
   A builder that supports generated strongly-typed route helpers for
   package:go_router
-version: 1.0.11
+version: 1.0.12
 repository: https://github.com/flutter/packages/tree/main/packages/go_router_builder
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router_builder%22
 
diff --git a/packages/go_router_builder/test/builder_test.dart b/packages/go_router_builder/test/builder_test.dart
index bcd25d2..147e825 100644
--- a/packages/go_router_builder/test/builder_test.dart
+++ b/packages/go_router_builder/test/builder_test.dart
@@ -31,4 +31,5 @@
   'NullableRequiredParam',
   'UnsupportedType',
   'theAnswer',
+  'EnumParam',
 };
diff --git a/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart b/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart
index 03a7ded..ca204ef 100644
--- a/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart
+++ b/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart
@@ -70,3 +70,49 @@
   MissingPathParam({required this.id});
   final String id;
 }
+
+@ShouldGenerate(r'''
+GoRoute get $enumParam => GoRouteData.$route(
+      path: '/:y',
+      factory: $EnumParamExtension._fromState,
+    );
+
+extension $EnumParamExtension on EnumParam {
+  static EnumParam _fromState(GoRouterState state) => EnumParam(
+        y: _$EnumTestEnumMap._$fromName(state.params['y']!),
+      );
+
+  String get location => GoRouteData.$location(
+        '/${Uri.encodeComponent(_$EnumTestEnumMap[y]!)}',
+      );
+
+  void go(BuildContext context) => context.go(location, extra: this);
+
+  void push(BuildContext context) => context.push(location, extra: this);
+}
+
+const _$EnumTestEnumMap = {
+  EnumTest.a: 'a',
+  EnumTest.b: 'b',
+  EnumTest.c: 'c',
+};
+
+extension<T extends Enum> on Map<T, String> {
+  T _$fromName(String value) =>
+      entries.singleWhere((element) => element.value == value).key;
+}
+''')
+@TypedGoRoute<EnumParam>(path: '/:y')
+class EnumParam extends GoRouteData {
+  EnumParam({required this.y});
+  final EnumTest y;
+}
+
+enum EnumTest {
+  a(1),
+  b(3),
+  c(5);
+
+  const EnumTest(this.x);
+  final int x;
+}