Lesson 14 / 25

Patterns and Switch Expressions

Match and destructure data with patterns in switch, if-case and variable declarations.

Asking questions about the shape of data

Dart 3 patterns test a value's shape and extract parts of it. Pattern kinds include constant patterns (404), relational patterns (>= 500), logical || and &&, type tests (int n), object patterns (Point(x: 0, :final y)), list patterns ([first, ..., last], with ... for the rest), map patterns ({'status': 'ok', 'data': final data}), record patterns and wildcards (_). They work in switch statements and expressions, in if-case (if (json case {'name': String name})), in variable declarations and in for loops. Switch expressions (final label = switch (code) { 200 => 'OK', >= 500 => 'Server error', _ => 'Other' };) return values concisely. Guard clauses with when add conditions. Over sealed types, enums and bools, switches are checked for exhaustiveness. Map patterns are particularly useful for validating decoded JSON, replacing chains of is checks and casts.

Validating JSON with patterns

Map and list patterns check structure and extract values in one step.

import 'dart:convert';

String describeStatus(int code) => switch (code) {
      200 || 201 => 'Success',
      >= 400 && < 500 => 'Client error',
      >= 500 => 'Server error',
      _ => 'Unexpected',
    };

String summarise(Object? json) {
  if (json case {'id': String id, 'items': [_, ...] && List items, 'total': num total}) {
    return 'Order $id: ${items.length} items, total $total';
  }
  return 'Invalid order payload';
}

String firstAndLast(List<int> values) => switch (values) {
      [] => 'empty',
      [final only] => 'only $only',
      [final first, ..., final last] => 'from $first to $last',
    };

void main() {
  final payload = jsonDecode('{"id":"o-7","items":[{"sku":"pen"}],"total":99}');
  print(summarise(payload));          // Order o-7: 1 items, total 99
  print(describeStatus(503));
  print(firstAndLast([3, 8, 15]));
}

A customs officer with a checklist

A pattern is a customs officer who checks each parcel against a description ("has an id string and a non-empty item list") and, if it matches, hands you the labelled contents directly instead of making you open it yourself.

Quick check: What does the list pattern `[final first, ..., final last]` match?

  • Only lists with exactly three elements
  • Empty lists
  • Maps
  • Lists with at least two elements, binding the first and last
Answer

Lists with at least two elements, binding the first and last — The rest element ... matches any number of elements between first and last.