Boost your productivity with powerful and expressive Dart extensions.
This lightweight package enriches core Dart types like List
, Map
, String
, num
, and DateTime
with intuitive, time-saving methods โ making your code cleaner, faster to write, and easier to maintain.
Whether you're building apps, scripts, or libraries, extensions
gives you the fluent utility syntax you've always wanted โ no clutter, just results.
Stop repeating boilerplate logic. Start focusing on what matters.
Features
- ๐ง Write cleaner and more expressive Dart code with minimal effort.
- ๐งฉ Dozens of handy extensions for
List
,Map
,String
,DateTime
,num
, andSet
. - ๐ Reduce boilerplate with concise one-liners for common tasks.
- โ Improve readability and maintainability of your codebase.
- ๐ Chain transformations and filters with fluent-like syntax.
- ๐งช Built-in null-safety and edge-case handling.
- โ๏ธ Lightweight and fast โ perfect for mobile, backend, or CLI tools.
- ๐ง Fully documented and production-ready.
Getting started
Add this to your pubspec.yaml
:
dependencies:
extensions: ^latest
Then run:
flutter pub get
or
dart pub get
Import it in your Dart code:
import 'package:octopusllc/extensions.dart';
Map Extensions
mergeWith
final Map<String, dynamic> settings = {
'tasks': {'type': 'agent', 'icon': 'add'},
};
final Map<String, dynamic> i18n = {
'tasks': {'title': 'Tasks'},
'goals': {'title': 'Goals'},
};
final Map<String, dynamic> merged = settings.mergeWith(i18n);
/* RESULT
{
'tasks': {'type': 'agent', 'icon': 'add', 'title': 'Tasks'},
'goals': {'title': 'Goals'},
}
*/
getByField
final List<Map<String, dynamic>> users = [
{'name': 'Alice'},
{'name': 'Bob'},
{'name': 'Charlie'},
];
final List<String> names = users.getByField<String>('name');
/* RESULT
[Alice, Bob, Charlie]
*/
filterByKeys
final Map<String, dynamic> data = {
'a': {'value': 1},
'b': {'value': 2},
};
final Map<String, dynamic> filtered = data.filterByKeys(['b']);
/* RESULT
{'b': {'value': 2'}}
*/
filterBy
final Map<String, Map<String, dynamic>> data = {
'monday': {
'1': {'type': 'workout'},
'2': {'type': 'rest'},
},
};
final Map<String, dynamic> result = data.filterBy('type', 'workout');
/* RESULT
{
'monday': {
'1': {'type': 'workout'}
}
}
*/
countByField
final Map<String, Map<String, Map<String, dynamic>>> data = {
'day1': {
'e1': {'type': 'meeting'},
'e2': {'type': 'call'},
},
'day2': {
'e3': {'type': 'meeting'},
},
};
final Map<String, int> counts = data.countByField('type');
/* RESULT
{'meeting': 2, 'call': 1}
*/
groupByChildField
final Map<String, Map<String, String>> colors = {
'c1': {'group': 'spring'},
'c2': {'group': 'summer'},
'c3': {'group': 'spring'},
};
final Map<String, Map<String, Map<String, String>>> grouped = colors.groupByChildField('group');
/* RESULT
{
'spring': {
'c1': {'group': 'spring'},
'c3': {'group': 'spring'}
},
'summer': {
'c2': {'group': 'summer'}
}
}
*/
filterByValue
final Map<String, Map<String, dynamic>> data = {
'1': {'type': 'goal'},
'2': {'type': 'task'},
};
final Map<String, Map<String, dynamic>> filtered = data.filterByValue('type', 'goal');
/* RESULT
{'1': {'type': 'goal'}}
*/
groupByField
final Map<String, Map<String, Map<String, dynamic>>> data = {
'1': {
'a': {'priority': 'high'},
'b': {'priority': 'low'},
},
};
final Map<String, List<Map<String, dynamic>>> grouped = data.groupByField('priority');
/* RESULT
{
'high': [{'priority': 'high'}],
'low': [{'priority': 'low'}]
}
*/
stringValuesOnly
final Map<String, dynamic> map = {
'created': DateTime(2022, 1, 1),
'name': 'Alice',
};
final Map<String, dynamic> result = map.stringValuesOnly;
/* RESULT
{created: 2022-01-01 00:00:00.000, name: Alice}
*/
convertAllValuesToString
final Map<String, dynamic> data = {
'name': 'Alice',
'details': {
'birthday': DateTime(1990, 1, 1),
},
};
final Map<String, dynamic> result = data.convertAllValuesToString();
/* RESULT
{
name: Alice,
details: {birthday: 1990-01-01T00:00:00.000}
}
*/
getOptionsAsList
final Map<String, Map<String, dynamic>> strategies = {
's1': {'type': 'growth'},
's2': {'type': 'risk'},
};
final Map<String, List<Map<String, dynamic>>> grouped = strategies.getOptionsAsList(byField: 'type');
/* RESULT
{
'growth': [{'strategy': 's1'}],
'risk': [{'strategy': 's2'}]
}
*/
getBoolList
final List<int> list = [0, 1, 2];
final List<bool> result = list.getBoolList;
/* RESULT
[true, false, false]
*/
toBoolList
final List<int> list = [0, 1, 2];
final List<bool> result = list.toBoolList(trueAtIndex: 1);
/* RESULT
[false, true, false]
*/
calculateAvarage
final Map<String, int> data = {'10': 2, '20': 4};
final double average = data.calculateAvarage;
/* RESULT
16.666666666666668
*/
sumValues
final Map<String, num> data = {'a': 5, 'b': 10};
final double sum = data.sumValues;
/* RESULT
15.0
*/
randomEntryByField
final Map<String, Map<String, dynamic>> data = {
'x': {'title': 'Alpha'},
'y': {'title': 'Beta'},
};
final String randomTitle = data.randomEntryByField('title');
/* RESULT
Alpha // or Beta (random)
*/
reversedKeys
final Map<String, dynamic> original = {'a': 1, 'b': 2};
final Map<String, dynamic> reversed = original.reversedKeys;
/* RESULT
{'b': 2, 'a': 1}
*/
List Extensions
random
final List<String> greetings = ["Hello!", "Hi!", "Welcome!"];
final String randomGreeting = greetings.random;
/* RESULT
"Hello!" // or "Hi!" or "Welcome!"
*/
withoutDups
final List<int> numbers = [1, 2, 3, 1, 4, 2, 5];
final List<int> uniqueNumbers = numbers.withoutDups;
/* RESULT
[1, 2, 3, 4, 5]
*/
clearSublist
final List<Map<String, dynamic>> tasks = [
{'name': 'Task 1', 'checks': [true, false]},
{'name': 'Task 2', 'checks': [false]}
];
final List<Map<String, dynamic>> cleared = tasks.clearSublist();
/* RESULT
[
{'name': 'Task 1', 'checks': []},
{'name': 'Task 2', 'checks': []}
]
*/
containsMapKey
final List<Map<String, dynamic>> items = [
{'id': 1},
{'name': 'Test'}
];
final bool hasKey = items.containsMapKey({'id': 5});
/* RESULT
true
*/
firstWhereOrNull
final List<int> numbers = [1, 3, 5];
final int? even = numbers.firstWhereOrNull((e) => e % 2 == 0);
/* RESULT
null
*/
containsAny
final List<int> list = [1, 2, 3];
final bool result = list.containsAny([0, 2]);
/* RESULT
true
*/
onlyOwned
class Obj {
final String ownerUID;
final String title;
Obj(this.ownerUID, this.title);
}
final List<Obj> data = [
Obj('u1', 'A'),
Obj('u2', 'B'),
Obj('u1', 'C'),
];
final List<Obj> owned = data.onlyOwned<Obj>('u1');
/* RESULT
[A, C]
*/
sortedByTimeOnly
final List<DateTime> times = [
DateTime(2024, 1, 1, 15),
DateTime(2024, 1, 1, 9),
];
final List<DateTime> sorted = times.sortedByTimeOnly((t) => t);
/* RESULT
[2024-01-01 09:00:00.000, 2024-01-01 15:00:00.000]
*/
sumByValue
final List<Map<String, dynamic>> data = [
{'value': 5},
{'value': 10}
];
final double total = data.sumByValue((e) => e['value']);
/* RESULT
15.0
*/
sortedByValue
final List<Map<String, dynamic>> data = [
{'priority': 3},
{'priority': 1},
];
final sorted = data.sortedByValue((e) => e['priority']);
/* RESULT
[{'priority': 1}, {'priority': 3}]
*/
groupBy
final List<Map<String, dynamic>> items = [
{'type': 'a'},
{'type': 'b'},
{'type': 'a'},
];
final grouped = items.groupBy((e) => e['type']);
/* RESULT
{
'a': [{'type': 'a'}, {'type': 'a'}],
'b': [{'type': 'b'}]
}
*/
mapToOptions
final List<Map<String, dynamic>> items = [
{'id': 't1', 'title': 'Task'},
{'id': 't2', 'title': 'Goal'}
];
final mapped = items.mapToOptions('id', 'title');
/* RESULT
{
't1': {'title': 'Task'},
't2': {'title': 'Goal'}
}
*/
slice
final List<int> nums = [10, 20, 30, 40, 50];
final List<int> mid = nums.slice(1, 3);
/* RESULT
[20, 30, 40]
*/
takeFirst / takeLast
final list = [1, 2, 3, 4, 5];
final start = list.takeFirst(2);
/* RESULT
[1, 2]
*/
final end = list.takeLast(2);
/* RESULT
[4, 5]
*/
second / third / fourth
final list = [1, 2, 3, 4];
// list.second; /* RESULT 2 */
// list.third; /* RESULT 3 */
// list.fourth; /* RESULT 4 */
joinToString
final list = [1, 2, 3];
final str = list.joinToString(separator: '-', prefix: '[', postfix: ']');
/* RESULT
[1]-[2]-[3]
*/
flatten
final list = [
[1, 2],
[3],
];
final flat = list.flatten();
/* RESULT
[1, 2, 3]
*/
chunked
final list = [1, 2, 3, 4, 5];
final chunks = list.chunked(2);
/* RESULT
[[1, 2], [3, 4], [5]]
*/
shuffled
final list = [1, 2, 3];
final result = list.shuffled(Random());
/* RESULT
random order of [1, 2, 3]
*/
distinctBy
final list = ['apple', 'banana', 'apple'];
final result = list.distinctBy((e) => e);
/* RESULT
['apple', 'banana']
*/
min / max
final list = [5, 2, 9];
final minVal = list.min(); /* RESULT 2 */
final maxVal = list.max(); /* RESULT 9 */
filterNotNull / mapNotNull
final list = ['A', null, 'B'];
final filtered = list.filterNotNull();
/* RESULT
['A', 'B']
*/
toHashSet
final list = [1, 2, 2, 3];
final set = list.toHashSet();
/* RESULT
{1, 2, 3}
*/
+ and - operators
final a = [1, 2];
final b = [2, 3];
final union = a + b;
/* RESULT
[1, 2, 2, 3]
*/
final diff = a - b;
/* RESULT
[1]
*/