Answer
Overview
text
dynamicdynamic — No Type Safety
text
dynamicdartdynamic value = 42; value = 'hello'; // ✅ No compile error value = [1, 2, 3]; // ✅ No compile error // NO compile-time protection dynamic list = [1, 2, 3]; list.nonExistent(); // ❌ Runtime error — NoSuchMethodError int x = list; // ❌ Runtime error — type mismatch
Generics — Type-Safe Reusability
Generics let you write one implementation that works for many types while maintaining full compile-time type safety.
dart// Generic class — T is a type parameter class Box<T> { T value; Box(this.value); T getValue() => value; void setValue(T newValue) { value = newValue; } } void main() { final intBox = Box<int>(42); intBox.setValue(100); // ✅ Only int allowed // intBox.setValue('hi'); // ❌ Compile error final strBox = Box<String>('hello'); strBox.setValue('world'); // ✅ // Type inference final autoBox = Box(3.14); // Box<double> inferred }
Generic Functions
dart// Generic function T getFirst<T>(List<T> items) { if (items.isEmpty) throw StateError('Empty list'); return items.first; // Returns T, not dynamic } // Usage final first = getFirst([1, 2, 3]); // int final name = getFirst(['Alice', 'Bob']); // String
Generic Constraints
dart// Constrain T to only numeric types T add<T extends num>(T a, T b) => (a + b) as T; add(3, 4); // ✅ int add(1.5, 2.5); // ✅ double // add('a', 'b'); // ❌ String doesn't extend num
In Flutter — Common Generic Usage
dart// BLoC — Bloc<Event, State> class CounterBloc extends Bloc<CounterEvent, int> { ... } // Riverpod — Provider<T> final counterProvider = StateNotifierProvider<CounterNotifier, int>(...); // Future and Stream Future<List<User>> fetchUsers() async { ... } Stream<String> kafkaStream() async* { ... } // Map and List Map<String, int> scores = {}; List<Widget> widgets = [];
Comparison
| Feature | text | Generics |
|---|---|---|
| Type checking | Runtime | Compile-time |
| IDE support | ❌ Limited | ✅ Full autocomplete |
| Safety | ❌ No | ✅ Yes |
| Reusability | ✅ Always | ✅ With type params |
| Performance | Slightly slower | ✅ No overhead |
Rule: Use Generics over
wherever possible. Generics give you flexibility AND type safety.textdynamiconly when truly dealing with unknown runtime types (like raw JSON parsing).textdynamic