dart-idiomatic-usage
SKILL.md
Dart Effective Strings and Collections
Goal
Analyzes and refactors Dart code to comply with the official "Effective Dart: Usage" guidelines specifically targeting string manipulation and collection handling. It enforces idiomatic syntax, optimizes performance by eliminating anti-patterns (like .length checks or .cast()), and ensures type-safe collection transformations. Assumes a modern Dart environment with null safety enabled.
Instructions
-
String Concatenation and Interpolation
- Scan the code for string concatenations using the
+operator. - Replace adjacent string literal concatenations with adjacent strings (no operator).
- Replace variable concatenations with string interpolation.
- Remove unnecessary curly braces in interpolations where the identifier is not followed by alphanumeric text.
// BAD var s1 = 'Hello ' + name + '!'; var s2 = 'Hi, ${name}!'; var s3 = 'Part 1 ' + 'Part 2'; // GOOD var s1 = 'Hello $name!'; var s2 = 'Hi, $name!'; var s3 = 'Part 1 ' 'Part 2'; - Scan the code for string concatenations using the
-
Collection Initialization
- Replace unnamed constructor calls for
Map,Set, andListwith collection literals. - Utilize the spread operator (
...,...?) and collectionif/forfor dynamic collection building instead of.add()or.addAll().
// BAD var addresses = Map<String, Address>(); var counts = Set<int>(); var args = <String>[]; args.addAll(options); if (flag != null) args.add(flag); // GOOD var addresses = <String, Address>{}; var counts = <int>{}; var args = [ ...options, if (flag != null) flag, ]; - Replace unnamed constructor calls for
-
Collection Emptiness Checks
- Identify any collection checks comparing
.lengthto0. - Replace them with
.isEmptyor.isNotEmpty.
// BAD if (items.length == 0) return; if (items.length > 0) process(items); // GOOD if (items.isEmpty) return; if (items.isNotEmpty) process(items); - Identify any collection checks comparing
-
Iteration Logic (Decision Tree) Evaluate how iterables are being processed and apply the following logic:
- IF iterating over a
Map-> THENmap.forEach((k, v) { ... })is acceptable. - IF applying an existing function (tear-off) to an
Iterable-> THEN useiterable.forEach(functionName). - IF executing a function literal/block on an
Iterable-> THEN use afor-inloop.
// BAD people.forEach((person) { person.greet(); }); // GOOD for (final person in people) { person.greet(); } // GOOD (Tear-off) people.forEach(print); - IF iterating over a
-
Type Filtering and Casting (Decision Tree) Evaluate how collections are transformed or filtered by type:
- IF filtering an iterable to a specific type -> THEN use
.whereType<T>(). Do NOT use.where((e) => e is T). - IF copying an iterable while preserving its original type -> THEN use
.toList(). - IF copying an iterable and changing its type -> THEN use
List<T>.from(iterable). - IF
.cast<T>()is used -> THEN refactor to avoid it. Prefer creating the collection with the correct type, casting elements on access, or eagerly casting withList<T>.from().
// BAD var ints = objects.where((e) => e is int).cast<int>(); var copy = List.from(iterable); // when type change isn't needed var casted = objects.cast<int>(); // GOOD var ints = objects.whereType<int>(); var copy = iterable.toList(); var casted = List<int>.from(objects); // Eager cast - IF filtering an iterable to a specific type -> THEN use
-
Validate-and-Fix Loop
- Review the refactored code.
- Verify that no
+operators remain for string concatenation. - Verify that
.cast()is completely eliminated unless explicitly justified by lazy-evaluation requirements. - STOP AND ASK THE USER: If the original code relies heavily on lazy evaluation via
.cast()and converting toList.from()might cause performance regressions on massive datasets, pause and ask: "Refactoring.cast()toList.from()forces eager evaluation. Is this collection large enough that we need to preserve lazy evaluation, or is eager instantiation acceptable?"
Constraints
- DO NOT use
Map(),Set(), orList()unnamed constructors. - DO NOT use
.length == 0or.length > 0for iterables. - DO NOT use
Iterable.forEach()with a function literal. - DO NOT use
.cast()when a nearby operation (likeList.from()or.map<T>()) will suffice. - DO NOT use
where((e) => e is T); strictly enforcewhereType<T>(). - DO NOT use
+for string concatenation of literals or variables. - PREFER string interpolation (
$variable) over concatenation. - PREFER the spread operator (
...) and collection-if/for over imperative.add()/.addAll()mutations. - AVOID curly braces in string interpolation unless required for expression evaluation or disambiguation.
Weekly Installs
13
Repository
dart-lang/skillsGitHub Stars
6
First Seen
Mar 17, 2026
Security Audits
Installed on
amp10
cline10
opencode10
cursor10
kimi-cli10
codex10