A bound on a type parameter restricts which types can fill it. T extends Named means T must implement Named, so the function body can safely call any member declared by Named. One generic function then handles every implementer.

Program

Play the program to call badge<T extends Named> on a City and a Country.

bounded_generics.dart
Replay: real traced execution (multi-file project)
abstract class Named {
  String get name;
}

class City implements Named {
  @override
  final String name;
  City(this.name);
}

class Country implements Named {
  @override
  final String name;
  Country(this.name);
}

String badge<T extends Named>(T item) => item.name.toUpperCase();

void main() {
  var paris = City('Paris');
  var france = Country('France');
  var labels = '${badge(paris)} / ${badge(france)}';
  print(labels);
}
  1. paris ← City(name: Paris)

    19void main() {20  var paris = City('Paris');21  var france = Country('France');
    values this stepCity(name: Paris)paris
  2. france ← Country(name: France)

    20var paris = City('Paris');21var france = Country('France');22var labels = '${badge(paris)} / ${badge(france)}';
    values this stepCountry(name: France)france
  3. return ← PARIS

    17String badge<T extends Named>(T item) => item.name.toUpperCase();
    values this stepPARISreturnCity (Named)TParisitem.name
  4. return ← FRANCE

    17String badge<T extends Named>(T item) => item.name.toUpperCase();
    values this stepFRANCEreturnCountry (Named)TFranceitem.name
  5. labels ← PARIS / FRANCE

    21var france = Country('France');22var labels = '${badge(paris)} / ${badge(france)}';23print(labels);
    values this stepPARIS / FRANCElabels
  6. print(labels);

    22  var labels = '${badge(paris)} / ${badge(france)}';23  print(labels);24}
    outputPARIS / FRANCE
    values this stepPARIS / FRANCElabels
type bound `T extends Named` says any type filling `T` must implement `Named`.
safe member access Inside `badge`, `item.name` is allowed because every valid `T` has it: no cast, no runtime check.
polymorphic reuse The same `badge` handles `City`, `Country`, and any future `Named` without changes.