A record can model success or failure without throwing, keeping the caller on one explicit path.

Program

Play the program to parse a valid port, then select an out-of-range value.

result_record.dart
({bool ok, int value}) parsePort(String text) {
  var parsed = int.tryParse(text);
  if (parsed == null) return (ok: false, value: 0);
  if (parsed < 1 || parsed > 65535) return (ok: false, value: 0);
  return (ok: true, value: parsed);
}

void main() {
  var text = ;
  var result = parsePort(text);
  print('${result.ok}:${result.value}');
}
({bool ok, int value}) parsePort(String text) {
  var parsed = int.tryParse(text);
  if (parsed == null) return (ok: false, value: 0);
  if (parsed < 1 || parsed > 65535) return (ok: false, value: 0);
  return (ok: true, value: parsed);
}

void main() {
  var text = ;
  var result = parsePort(text);
  print('${result.ok}:${result.value}');
}
named record `({bool ok, int value})` names fields on a lightweight result.
no exception Invalid data returns `ok: false` instead of throwing.
caller check The caller prints both the success flag and value.