Generic extension
- Dart course
- Expert
- Lesson 22/47
- 5 min
Learn to write generic extensions.
Generic extension
A generic extension is an extension that takes a type parameter. The extension ListFirst<T> on List<T> { T? firstOrNull() => isEmpty ? null : first; } declaration safely gets the first element of any list.
Generic extensions preserve type safety: [1, 2].firstOrNull() returns int?, ['a'].firstOrNull() returns String?. The type parameter T is inferred from the target type.
Type inference
In generic extensions, the type parameter is automatically inferred from the target. In extension BoxUnwrap<T> on Box<T> { T unwrap() => value; }, when called on a Box<int>, T becomes int.
The type parameter can also be specified explicitly: box<int>.unwrap(). But in most cases inference is sufficient. Generic extensions are ideal for adding functionality to generic classes or types.
Practice A ListMiddle extension
Define a ListMiddle<T> extension on List<T> with a T? middleOrNull() => isEmpty ? null : this[length ~/ 2]; method. In main add print([1, 2, 3].middleOrNull());.
Starter code
void main() {
// define a ListMiddle<T> extension (on List<T>; middleOrNull)
// print [1, 2, 3].middleOrNull()
}Sample solution
extension ListMiddle<T> on List<T> {
T? middleOrNull() => isEmpty ? null : this[length ~/ 2];
}
void main() {
print([1, 2, 3].middleOrNull());
}Expected output
2
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What does a generic extension provide?
- Function only for int
- Function only for String
- Type-safe multi-type function Correct answer
- Runtime type checking
Explanation: a generic extension works type-safely with multiple types.
2 Match the generic extension parts
| Term | Meaning |
|---|---|
<T> |
Type parameter |
on List<T> |
Target type |
T? |
Nullable return |
first |
First element |
3 A generic extension declaration
extension ListFirst<____> on List<T> {
T? firstOrNull() => isEmpty ? null : first;
}
extension ListFirst<T> on List<T> {
T? firstOrNull() => isEmpty ? null : first;
}
Explanation: extension ListFirst<T> takes a generic type parameter.