Search code examples
dartpattern-matchingrecorddestructuring

Dart nullable records with pattern matching: The matched value of type '(String, int)?' isn't assignable to the required type '(Object?, Object?)'


Given the following function:

(String, int)? getPair() {
  return ('hello', 42);
}

I can access the multiple returns using the fields like so:

final pair = getPair();
if (pair != null) {
  String word = pair.$1;
  int number = pair.$2;
}

However, I'd prefer to destructure the values using some sort of pattern matching. This is what I tried:

final (word, number) = getPair();

But that gives the following error:

The matched value of type '(String, int)?' isn't assignable to the required type '(Object?, Object?)'. Try changing the required type of the pattern, or the matched value type.

How would I change the required type of the pattern or the matched value?

Related reference:


Solution

  • You can do that destructuring after the null-check, like you did manually using $1 and $2:

    final pair = getPair();
    if (pair != null) {
      final (word, number) = pair;
      // ...
    }
    

    You can do a not-null assert as part of a declaration pattern:

    final ((word, number)!) = getPair();
    

    That will throw if the value is null.

    You cannot do a null check as part of a declaration, because declaration patterns must be irrefutable, and a check can fail.

    You can do the null check as part of a refutable pattern check, using ?:

    if (getPair() case (final word, final number)?) {
      // ...
    } // else { "or else, if needed"; }
    

    or

    switch (getPair()) {
      case (final word, final number)?: // ....
      // default: "or else, if needed";
    }
    

    Since you're then also matching the type in the following destructuring, the ? can be removed.

    Or you can combine the two approaches, if you also want the binding of pair:

    if (getPair() case final pair?) { // Bind `pair` if it's not `null`.
      final (word, number) = pair;
    }