Extension methods let you add new functionality to existing types and third-party library types without modifying the source code of the original class. Your IDE’s autocompletion will list extension methods alongside native methods.
You cannot alter APIs provided by others, yet you want to add convenient helper methods.
Sample requirement: Use '42'.parseInt() instead of int.parse('42').
Syntax Structure
extension ExtensionName? on TargetType {
// Methods, getters, setters, operators, static members
}Code language: JavaScript (javascript)
Example
// Place everything in a single file, no separation required; main runs directly
extension NumberParsing on String {
int parseInt() {
return int.parse(this);
}
double parseDouble() {
return double.parse(this);
}
}
void main() {
print('42'.parseInt()); // 42
print('3.14'.parseDouble()); // 3.14
print('100'.padLeft(6)); // Compare with built-in String method
}Code language: Dart (dart)
Output
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
42
3.14
100Code language: CSS (css)
The extension name is optional; this refers to the instance invoking the extension.
Supported Member Types for Extensions
Inside an extension you may define: instance methods, getters, setters, operators and static members.
extension StringExt on String {
// getter
bool get isEmptyOrBlank => trim().isEmpty;
// Instance method
String repeat(int count) => List.filled(count, this).join();
// Operator overloading
String operator *(int count) => repeat(count);
// Static member (accessed via extension name)
static String emptyStr = '';
static void printTip() => print("Static method of string extension");
}
void main() {
var str = " dart ";
print(str.isEmptyOrBlank);
print("hi" * 3);
print("hello".repeat(2));
// Access static members
print(StringExt.emptyStr);
StringExt.printTip();
}Code language: PHP (php)
Execution Result
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
false
hihihi
hellohello
Static method of string extensionCode language: PHP (php)
Unnamed Extensions (Anonymous Extensions)
Omit the extension name, making it visible only within the current library. Conflicts cannot be resolved with explicit invocation.
You cannot invoke it externally using the syntax ExtensionName(instance).
extension on String {
bool get isBlank => trim().isEmpty;
}
void main() {
print(" ".isBlank); // true
}Code language: Dart (dart)
Static members inside anonymous extensions can only be used within the extension itself.
Generic extensions
You can create extensions for generic types such as List<T>
extension MyFancyList<T> on List<T> {
int get doubleLength => length * 2;
List<T> operator -() => reversed.toList();
List<List<T>> split(int at) => [sublist(0, at), sublist(at)];
}
void main() {
List<int> list = [1, 2, 3, 4];
print(list.doubleLength); // 8
print(-list); // [4,3,2,1]
print(list.split(2)); // [[1,2],[3,4]]
}Code language: Dart (dart)
Execution Result
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
8
[4, 3, 2, 1]
[[1, 2], [3, 4]]Code language: CSS (css)
Static Types vs dynamic
dynamic variables cannot call extension methods
Extension methods are resolved statically. The type of a dynamic variable is determined at runtime, so extensions cannot be located:
void main() {
dynamic d = '2';
// print(d.parseInt()); // Throws NoSuchMethodError at runtime
var v = '2';
print(v.parseInt()); // Type inferred as String, works normally
}
extension NumberParsing on String {
int parseInt() => int.parse(this);
}Code language: JavaScript (javascript)
Reason: Extension methods bind based on the variable’s static type during compilation, not through runtime lookup.
Solutions for API Name Conflicts
Three approaches exist when multiple extensions contain identically named members.
1: Hide conflicting extensions using show / hide on import
// string_apis.dart contains NumberParsing
// string_apis_2.dart contains NumberParsing2, which also defines parseInt
import 'string_apis.dart';
import 'string_apis_2.dart' hide NumberParsing2;
void main() {
print('42'.parseInt()); // Uses implementation from string_apis.dart
}Code language: Dart (dart)
2: Explicitly call the extension (wrapper syntax)
import 'string_apis.dart'; // NumberParsing
import 'string_apis_2.dart'; // NumberParsing2
void main() {
// print('42'.parseInt()); // Conflict, compile error
print(NumberParsing('42').parseInt());
print(NumberParsing2('42').parseInt());
}Code language: Dart (dart)
3: Import libraries with prefixes
Use prefixes to distinguish extensions with identical names:
import 'string_apis.dart';
import 'string_apis_3.dart' as rad;
void main() {
print(NumberParsing('42').parseInt());
print(rad.NumberParsing('42').parseInt());
// Non-conflicting extension methods can still be invoked implicitly
print('42'.parseNum());
}Code language: Dart (dart)
Extension methods