Skip to main content
A record pattern is a declarative construct in Dart used to match, validate, and destructure Record types. It allows developers to extract positional and named fields from a record into distinct variables and perform inline type checking within pattern-matching contexts like switch statements, if-case clauses, and variable declarations.

Syntax and Destructuring

Record patterns mirror the syntax of record expressions but operate in reverse, binding the extracted values to variables. Positional Fields Positional fields are matched strictly by their order within the record.
// Destructuring via variable declaration
var (a, b) = (10, 'Dart'); 
Named Fields Named fields are matched by their explicit identifiers, regardless of their order. The syntax requires the field name followed by a colon and the variable to bind.
var (name: n, age: a) = (name: 'Alice', age: 30);
Dart provides a syntactic shorthand for named fields when the bound variable name matches the field name. Prefixing the identifier with a colon implicitly creates a variable of the same name.
var (:name, :age) = (name: 'Alice', age: 30);
// Equivalent to: var (name: name, age: age)

Pattern Matching and Control Flow

When used in control flow structures, record patterns act as predicates that evaluate to a boolean while simultaneously binding variables if the match succeeds.
final record = (1, 'success');

if (record case (int code, String message)) {
  print(code);    // Binds 1 to `code`
  print(message); // Binds 'success' to `message`
}

Advanced Mechanics

Nested Subpatterns Record patterns can contain nested subpatterns, allowing for deep destructuring of complex, multi-layered data structures.
final complexRecord = (1, (x: 2, y: 3));

switch (complexRecord) {
  case (int id, (:var x, :var y)):
    print('$id, $x, $y');
}
Wildcards The underscore _ acts as a wildcard pattern to discard specific positional fields without binding them to a variable or allocating memory for them.
var (first, _, third) = (10, 20, 30);
Type Checking and Casting Patterns can enforce type constraints on individual fields. If the runtime type of the record’s field does not match the pattern’s type annotation, the match fails safely without throwing an exception.
dynamic data = (1, 2.5);

switch (data) {
  case (int a, String b):
    // Match fails: Second field is double, not String
    break;
  case (int a, double b):
    // Match succeeds: Types align, variables 'a' and 'b' are bound
    break;
}
Tired of Poor Dart Skills? Fix That With Deep Grasping!Learn More