Sometimes we run into a case when a function logically needs to return multiple values. Some examples are returning coordinates of a point, returning some statistical data, returning error information like the error code and the message, etc.

Important

Records require a language version of at least 3.0.

Previously, when we wanted to return more than one object from a function, we had to create an additional class or add a package like Tuple.

The following code snippet shows that to return the name and age from a function, we had to create a class called User:

void main() {
  final user = getUser();
  print('Name: ${user.name}'); // Prints 'John'
  print('Age: ${user.age}'); // Prints '30'
}
 
User getUser() {
  return User('John', 30);
}
 
class User {
  final String name;
  final int age;
  User(this.name, this.age);
}

Now let’s see the difference using records.

void main() {
  final user = getUser();
  print('Name: ${user.name}'); // Prints 'John'
  print('Age: ${user.age}'); // Prints '30'
}
 
({String name, int age}) getUser() {
  return (name: 'John', age: 30);
}

We can see that using records, it is not necessary to create a User class.

Records Syntax

Records expressions are comma-delimited lists of named or positional fields, enclosed in parentheses:

void main() {
  final user = (name: 'John', age: 30);
  print('Name: ${user.name}'); // Prints 'John'
  print('Age: ${user.age}'); // Prints '30'
 
  final anime = ('One Piece', 500);
  print('Name: ${anime.$1}'); // Prints 'One Piece'
  print('Episodes: ${anime.$2}'); // Prints '500'
 
  final record = ('first', a: 2, b: true, 'last');
  print(record.$1); // Prints 'first'
  print(record.a); // Prints 2
  print(record.b); // Prints true
  print(record.$2); // Prints 'last'
}

Records and Pattern Destructuring

We can even use destructuring, which is a pattern matching technique, to extract and assign values from a data structure into individual variables concisely and efficiently. The code would look like this:

void main() {
  final (:name, :age) = getUser();
  print('Name: $name'); // Prints 'John'
  print('Age: $age'); // Prints '30'
}
 
({String name, int age}) getUser() {
  return (name: 'John', age: 30);
}