App Icon

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, and Set.
  • ๐Ÿš€ 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]
*/

Libraries

extensions