Patterns and Destructuring
Prerequisites: Records, switch statements and expressions
Patterns (Dart 3+) describe the shape of a value. They let you check that shape and pull out the parts you need in one step — destructuring.
Destructuring in declarations
void main() {
final (name, age) = ('Ada', 36);
print('$name is $age');
final [first, second, ...rest] = [1, 2, 3, 4, 5];
print('$first $second $rest');
final {'host': host, 'port': port} = {'host': 'localhost', 'port': 8080};
print('$host:$port');
var a = 1;
var b = 2;
(a, b) = (b, a);
print('$a $b');
}
Ada is 36
1 2 [3, 4, 5]
localhost:8080
2 1
...restcollects the remaining list elements.- Map patterns pull out values by key.
(a, b) = (b, a)swaps two variables in one line.
Patterns in switch
Patterns are most powerful in switch, where they match structure:
String describe(Object command) => switch (command) {
['add', String item] => 'Adding $item',
['move', String from, String to] => 'Moving $from to $to',
[] => 'Empty command',
[String cmd, ...] => 'Unknown command: $cmd',
(int x, int y) when x == y => 'A diagonal point',
(int x, int y) => 'Point at $x, $y',
_ => 'Not a command',
};
void main() {
print(describe(['add', 'milk']));
print(describe(['move', 'a', 'b']));
print(describe(['jump', 'high']));
print(describe((2, 2)));
print(describe((1, 5)));
print(describe(42));
}
Adding milk
Moving a to b
Unknown command: jump
A diagonal point
Point at 1, 5
Not a command
Validating JSON-like data with if-case
if (value case pattern) checks a single pattern — ideal for data from
outside your program:
void main() {
final Object json = {'user': {'name': 'Ada', 'age': 36}};
if (json case {'user': {'name': String name, 'age': int age}}) {
print('$name is $age');
} else {
print('Unexpected shape');
}
}
Ada is 36
One pattern checks that json is a map, has a user map inside, and
that name is a String and age is an int — then binds both.
Object patterns
ClassName(field: pattern) matches an object and reads its fields:
class Point {
final int x, y;
const Point(this.x, this.y);
}
void main() {
const p = Point(0, 7);
final label = switch (p) {
Point(x: 0, y: 0) => 'origin',
Point(x: 0) => 'on the y-axis',
Point(:final x, :final y) => 'at $x, $y',
};
print(label);
}
on the y-axis
:final x is shorthand for x: final x.