Skip to main content
A record pattern matches a record object by verifying its shape (arity and field names) and recursively matching its field values against corresponding subpatterns. It is primarily used to destructure record types and bind values to variables in pattern matching contexts, declarations, and assignments.

Syntax Structure

A record pattern consists of a parenthesized list of subpatterns representing positional and named fields. Crucial Distinction: To distinguish a record pattern containing exactly one positional field from a parenthesized subpattern (which merely groups a pattern), a trailing comma is mandatory. Without the comma, the compiler treats the syntax as a parenthesized expression rather than a record pattern. Named fields do not require a trailing comma for disambiguation.
// Multiple positional fields
(subpattern1, subpattern2)

// Single positional field (Trailing comma is required)
(subpattern1,) 

// Named fields
(name: subpattern1)

// Mixed positional and named
(subpattern1, name: subpattern2, :variableName)

Positional Field Matching

Positional subpatterns match the subject record’s fields based strictly on ordinal position. The matching is exhaustive regarding arity: the number of positional subpatterns in the pattern must exactly match the number of positional fields in the subject record type. If the static type of the subject record is known, a mismatch in the number of positional fields results in a compile-time error.
var record = (10, 'string');

switch (record) {
  case (10, var s):
    print(s); // Output: string
    
  // case (10): 
  //   Compile-time error: The pattern requires 1 positional field, 
  //   but the record type has 2.
}

Named Field Matching

Named subpatterns match based on the field key, independent of their physical order in the pattern. Unlike positional matching, named field matching is not exhaustive; a record pattern does not need to match every named field present in the subject record. Fields present in the subject but omitted from the pattern are ignored.
var record = (x: 10, y: 20, z: 30);

// Match: 'x' and 'y' are matched; 'z' is ignored.
switch (record) {
  case (y: var yVal, x: 10): 
    print(yVal); // Output: 20
}

Variable Binding Shorthand

When binding a named field to a variable of the same name, the explicit field key can be omitted by prefixing the variable name with a colon. The syntax :name is syntactic sugar for name: name. The variable created by this shorthand infers its storage semantics (e.g., var, final) from the enclosing declaration context.
var record = (width: 100, height: 200);

// Equivalent to: var (width: width, height: height) = record;
var (:width, :height) = record;

Type Annotation and Checking

Record patterns can assert specific types for individual fields by using variable patterns with type annotations or object patterns. If the runtime type of a field does not match the annotated type in the subpattern, the entire record match fails.
(num, Object) record = (1, 's');

switch (record) {
  // Matches only if the first field is specifically an int
  // and the second field is specifically a String.
  case (int i, String s):
    print('Matched types');
}

Wildcards

The wildcard pattern (_) matches any value without binding it to a variable. In record patterns, wildcards are frequently used to satisfy the strict positional arity requirement while discarding specific field values.
var record = (1, 2, 3);

// Matches a 3-element record, discarding the second element
var (first, _, third) = record;

Recursive Composition

Record patterns are composable; a subpattern within a record pattern can be any valid pattern, including another record pattern, a list pattern, or an object pattern. This allows for deep destructuring of nested data structures.
var complex = (user: (id: 1, name: 'A'), flags: [true, false]);

// Nested record pattern matches 'user', then nested list pattern matches 'flags'
if (complex case (user: (id: var id), flags: [true, _])) {
  print(id); // Output: 1
}
Master Dart with Deep Grasping Methodology!Learn More