← Flutter & Dart

Dart Fundamentals

What do the cascade operator (`..`), the spread (`...`), and the collection operators (`if`/`for` inside lists) do in Dart?

Show answer — try answering out loud first

The cascade operator .. lets you call several methods on the same object without repeating its name. The spread ... inserts all the elements of one collection into another. Collection if and collection for let you build lists with conditional logic or loops directly inside the brackets.

  • Cascade (..): instead of writing the object over and over, you chain operations on it. Each .. operates on the original object (not on what the method returns). Very common when configuring objects.
  • Spread (...): "spreads out" the elements of one collection into another. ...otherList drops in all of its elements. There's a null-aware version ...? that doesn't fail if the collection is null.
  • Collection if / for: you can put an if or a for inside a list definition to include elements conditionally or generate them in a loop. It's used a ton in Flutter to build lists of widgets.
class Dog {
  String name = "";
  int age = 0;
  void bark() => print("$name says woof");
}

void main() {
  // Cascade: configure the same object without repeating it
  final dog = Dog()
    ..name = "Rex"
    ..age = 3
    ..bark(); // "Rex says woof"
  print("${dog.name}, ${dog.age}"); // "Rex, 3"

  // Spread: insert elements from another list
  final base = [1, 2, 3];
  final extended = [0, ...base, 4];
  print(extended); // [0, 1, 2, 3, 4]

  // Null-aware spread
  List<int>? maybeNull;
  final safe = [0, ...?maybeNull, 5];
  print(safe); // [0, 5]

  // Collection if / for
  bool showExtra = true;
  final items = [
    "a",
    for (var i = 0; i < 3; i++) "item$i",
    if (showExtra) "extra",
  ];
  print(items); // [a, item0, item1, item2, extra]
}

Confusing the cascade .. with regular access .. With .., the whole expression returns the original object, not the method's result. If you do final x = list..add(1);, x is the list, not the result of add. If you mistakenly used . expecting to chain, you'd get the method's return value, which is usually void or something different.

"The cascade .. lets me configure or call several methods on the same object without repeating its name, and it always returns the original object. The spread ... inserts the elements of one collection into another, and it has the ...? variant that ignores a null value. And collection if and collection for let me build lists with conditionals and loops right inside the brackets, something I use a lot in Flutter to build lists of widgets conditionally."

Quick challenge

What does this code print?

final a = [1, 2];
final b = [...a, if (a.length > 1) 99];
print(b);
See answer

It prints [1, 2, 99]. The spread ...a drops in 1 and 2. Then the collection if evaluates a.length > 1, which is true (the length is 2), so it adds 99.