Dart Pattern Matching

Summary: in this tutorial, you’ll learn how to use Dart pattern matching to perform switch but for types, collections and object properties.

What is Pattern Matching? #

Dart 3 introduced Pattern matching feature that lets you:

  • Match against types.
  • Destructure data directly from records, lists, and objects.
  • Extract variables inline.

The pattern matching works like switch statement but for for types, collections, and object properties.

Type Patterns #

Type patterns allows you to check if a value is a certain type and extract it into a variable.

The following example uses type patterns to log analytic events with various payloads:

void logEvent(Object payload) {
  switch (payload) {
    case int id:
      print('Event ID: $id');
      break;
    case String name:
      print('Event Name: $name');
      break;
    default:
      print('Unknown event type');
  }
}Code language: Dart (dart)

In this example:

  • First, check if payload is an int or String.
  • Second, if it matches, assign the value a variable (id or name) and use inside the case block.

Type patterns help you avoid manual checking using the is operator and casting.

Record Patterns #

The record patterns allow you to extract values from records using position or name.

For example, the following show how to use record patterns to handle geolocation data from a sensor:

void handleCoordinates((double, double) position) {
  switch (position) {
    case (double lat, double lng):
      print('Latitude: $lat, Longitude: $lng');
      break;
  }
}
Code language: Dart (dart)

In this example:

  • First, destructure a record (double, double) into lat and lng variables.
  • Second, use these variables inside the case.

The following example shows how to use named record fields to extract data from a record:

void handleUser(({String name, int age}) user) {
  switch (user) {
    case (:var name, :var age):
      print('User $name is $age years old.');
  }
}
Code language: Dart (dart)

In this example:

  • First, match named fields name and age from the user record.
  • Second, extract values into name and age variables.

Inline Matching with if-case #

The if-case allows you to match and extract data within the conditions.

For example, the following illustrates how to render UI based on user type using if-case for inline matching:

Object user = 'admin';

if (user case String role && role == 'admin') {
  print('Show admin panel');
}
Code language: Dart (dart)

In this example:

  • First, match if user is a String and equals 'admin'.
  • Second, perform type checking and condition in one line (inline).

List Patterns #

The list patterns allows you to match list structure and extract items.

For example, the following shows how to use list patterns to parse the command line arguments (CLI):

void parseCommand(List<String> args) {
  switch (args) {
    case ['create', String name]:
      print('Creating item: $name');
      break;
    case ['delete', String id]:
      print('Deleting item with ID: $id');
      break;
    default:
      print('Unknown command');
  }
}
Code language: Dart (dart)

In this example:

  • First, match a fixed list patterns like ['create', String name] and [‘delete’, String id]
  • Second, bind each item to a variable (name or id).
  • Third, use the variables directly in the case.

Map Patterns #

Map patterns allow you to match maps and extract values by keys.

For example, the following shows how to use map patterns to parse HTTP response payload:

void handleResponse(Map<String, dynamic> json) {
  switch (json) {
    case {'status': String status, 'message': String msg}:
      print('Status: $status\nMessage: $msg');
      break;
    default:
      print('Unexpected response');
  }
}Code language: Dart (dart)

How it works:

  • First, match the keys status and message and extract their values.
  • Second, fall to default when the keys or types don’t match.

Pattern Matching in if and while #

Pattern matching in if and while lets you write clean conditional logic.

The following example shows how to use pattern matching in an if statement to print out API version in the payload:

Object payload = (version: 2, content: 'Hello');

if (payload case (:var version, :var content)) {
  print('Version $version says $content');
}Code language: Dart (dart)

How it works:

  • First, match a named record.
  • Second, extracts both version and content if matched.

Sealed Class Pattern Matching #

For sealed class pattern matching, check out the sealed class tutorial.

Summary #

FeatureSyntax ExampleUse Case
Type patterncase int x:Type-safe branching
Record destructuringcase (:name, :age):Extract user info
if-caseif (x case int y && y > 5)Conditional matching
List patterncase ['create', id]:CLI argument parsing
Map patterncase {'status': s}JSON parsing
Was this tutorial helpful ?