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 anint
orString
. - Second, if it matches, assign the value a variable (
id
orname
) 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)
intolat
andlng
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
andag
e from the user record. - Second, extract values into
name
andage
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 aString
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
orid
). - 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
andmessage
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
andcontent
if matched.
Sealed Class Pattern Matching #
For sealed class pattern matching, check out the sealed class tutorial.
Summary #
Feature | Syntax Example | Use Case |
---|---|---|
Type pattern | case int x: | Type-safe branching |
Record destructuring | case (:name, :age): | Extract user info |
if-case | if (x case int y && y > 5) | Conditional matching |
List pattern | case ['create', id]: | CLI argument parsing |
Map pattern | case {'status': s} | JSON parsing |